blob: 7fb5aa0182782c2234e497dc16d56e8d447167e9 [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
Emeric Brunfc0421f2012-09-07 17:30:07 +0200261/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
262 * an early error happens and the caller must call SSL_CTX_free() by itelf.
263 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200264int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200265{
266 BIO *in;
267 X509 *x = NULL, *ca;
268 int i, len, err;
269 int ret = -1;
270 int order = 0;
271 X509_NAME *xname;
272 char *str;
273 struct sni_ctx *sc;
274#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
275 STACK_OF(GENERAL_NAME) *names;
276#endif
277
278 in = BIO_new(BIO_s_file());
279 if (in == NULL)
280 goto end;
281
282 if (BIO_read_filename(in, file) <= 0)
283 goto end;
284
285 x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
286 if (x == NULL)
287 goto end;
288
289#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
290 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
291 if (names) {
292 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
293 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
294 if (name->type == GEN_DNS) {
295 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
296 if ((len = strlen(str))) {
297 int j;
298
299 if (*str != '*') {
300 sc = malloc(sizeof(struct sni_ctx) + len + 1);
301 for (j = 0; j < len; j++)
302 sc->name.key[j] = tolower(str[j]);
303 sc->name.key[len] = 0;
304 sc->order = order++;
305 sc->ctx = ctx;
306 ebst_insert(&s->sni_ctx, &sc->name);
307 }
308 else {
309 sc = malloc(sizeof(struct sni_ctx) + len);
310 for (j = 1; j < len; j++)
311 sc->name.key[j-1] = tolower(str[j]);
312 sc->name.key[len-1] = 0;
313 sc->order = order++;
314 sc->ctx = ctx;
315 ebst_insert(&s->sni_w_ctx, &sc->name);
316 }
317 }
318 OPENSSL_free(str);
319 }
320 }
321 }
322 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
323 }
324#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
325
326 xname = X509_get_subject_name(x);
327 i = -1;
328 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
329 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
330 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
331 if ((len = strlen(str))) {
332 int j;
333
334 if (*str != '*') {
335 sc = malloc(sizeof(struct sni_ctx) + len + 1);
336 for (j = 0; j < len; j++)
337 sc->name.key[j] = tolower(str[j]);
338 sc->name.key[len] = 0;
339 sc->order = order++;
340 sc->ctx = ctx;
341 ebst_insert(&s->sni_ctx, &sc->name);
342 }
343 else {
344 sc = malloc(sizeof(struct sni_ctx) + len);
345 for (j = 1; j < len; j++)
346 sc->name.key[j-1] = tolower(str[j]);
347 sc->name.key[len-1] = 0;
348 sc->order = order++;
349 sc->ctx = ctx;
350 ebst_insert(&s->sni_w_ctx, &sc->name);
351 }
352 }
353 OPENSSL_free(str);
354 }
355 }
356
357 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
358 if (!SSL_CTX_use_certificate(ctx, x))
359 goto end;
360
361 if (ctx->extra_certs != NULL) {
362 sk_X509_pop_free(ctx->extra_certs, X509_free);
363 ctx->extra_certs = NULL;
364 }
365
366 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata))) {
367 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
368 X509_free(ca);
369 goto end;
370 }
371 }
372
373 err = ERR_get_error();
374 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
375 /* we successfully reached the last cert in the file */
376 ret = 1;
377 }
378 ERR_clear_error();
379
380end:
381 if (x)
382 X509_free(x);
383
384 if (in)
385 BIO_free(in);
386
387 return ret;
388}
389
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200390static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200391{
392 int ret;
393 SSL_CTX *ctx;
394
395 ctx = SSL_CTX_new(SSLv23_server_method());
396 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200397 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
398 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200399 return 1;
400 }
401
402 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200403 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
404 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200405 SSL_CTX_free(ctx);
406 return 1;
407 }
408
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200409 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200410 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200411 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
412 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200413 if (ret < 0) /* serious error, must do that ourselves */
414 SSL_CTX_free(ctx);
415 return 1;
416 }
Emeric Brun61694ab2012-10-26 13:35:33 +0200417
418 if (SSL_CTX_check_private_key(ctx) <= 0) {
419 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
420 err && *err ? *err : "", path);
421 return 1;
422 }
423
Emeric Brunfc0421f2012-09-07 17:30:07 +0200424 /* we must not free the SSL_CTX anymore below, since it's already in
425 * the tree, so it will be discovered and cleaned in time.
426 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200427#ifndef OPENSSL_NO_DH
428 ret = ssl_sock_load_dh_params(ctx, path);
429 if (ret < 0) {
430 if (err)
431 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
432 *err ? *err : "", path);
433 return 1;
434 }
435#endif
436
Emeric Brunfc0421f2012-09-07 17:30:07 +0200437#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200438 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200439 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
440 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +0200441 return 1;
442 }
443#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200444 if (!bind_conf->default_ctx)
445 bind_conf->default_ctx = ctx;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200446
447 return 0;
448}
449
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200450int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200451{
452 struct dirent *de;
453 DIR *dir;
454 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +0100455 char *end;
456 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200457 int cfgerr = 0;
458
459 if (!(dir = opendir(path)))
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200460 return ssl_sock_load_cert_file(path, bind_conf, curproxy, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200461
462 /* strip trailing slashes, including first one */
463 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
464 *end = 0;
465
Emeric Brunfc0421f2012-09-07 17:30:07 +0200466 while ((de = readdir(dir))) {
Willy Tarreauee2663b2012-12-06 11:36:59 +0100467 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200468 if (stat(fp, &buf) != 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200469 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
470 err && *err ? *err : "", fp, strerror(errno));
Emeric Brunfc0421f2012-09-07 17:30:07 +0200471 cfgerr++;
472 continue;
473 }
474 if (!S_ISREG(buf.st_mode))
475 continue;
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200476 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, curproxy, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200477 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200478 closedir(dir);
479 return cfgerr;
480}
481
Thierry Fournier383085f2013-01-24 14:15:43 +0100482/* Make sure openssl opens /dev/urandom before the chroot. The work is only
483 * done once. Zero is returned if the operation fails. No error is returned
484 * if the random is said as not implemented, because we expect that openssl
485 * will use another method once needed.
486 */
487static int ssl_initialize_random()
488{
489 unsigned char random;
490 static int random_initialized = 0;
491
492 if (!random_initialized && RAND_bytes(&random, 1) != 0)
493 random_initialized = 1;
494
495 return random_initialized;
496}
497
Emeric Brunfc0421f2012-09-07 17:30:07 +0200498#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
499#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
500#endif
501
502#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
503#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
Willy Tarreau7d588ee2012-11-26 18:47:31 +0100504#define SSL_renegotiate_pending(arg) 0
Emeric Brunfc0421f2012-09-07 17:30:07 +0200505#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200506#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
507#define SSL_OP_SINGLE_ECDH_USE 0
508#endif
Emeric Brun2d0c4822012-10-02 13:45:20 +0200509#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
510#define SSL_OP_NO_TICKET 0
511#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200512#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
513#define SSL_OP_NO_COMPRESSION 0
514#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +0200515#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
516#define SSL_OP_NO_TLSv1_1 0
517#endif
518#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
519#define SSL_OP_NO_TLSv1_2 0
520#endif
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200521#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
522#define SSL_OP_SINGLE_DH_USE 0
523#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200524#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
525#define SSL_OP_SINGLE_ECDH_USE 0
526#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200527#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
528#define SSL_MODE_RELEASE_BUFFERS 0
529#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200530int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy *curproxy)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200531{
532 int cfgerr = 0;
533 int ssloptions =
534 SSL_OP_ALL | /* all known workarounds for bugs */
535 SSL_OP_NO_SSLv2 |
536 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200537 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +0200538 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +0200539 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
540 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200541 int sslmode =
542 SSL_MODE_ENABLE_PARTIAL_WRITE |
543 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
544 SSL_MODE_RELEASE_BUFFERS;
545
Thierry Fournier383085f2013-01-24 14:15:43 +0100546 /* Make sure openssl opens /dev/urandom before the chroot */
547 if (!ssl_initialize_random()) {
548 Alert("OpenSSL random data generator initialization failed.\n");
549 cfgerr++;
550 }
551
Emeric Brun89675492012-10-05 13:48:26 +0200552 if (bind_conf->ssl_options & BC_SSL_O_NO_SSLV3)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200553 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brun89675492012-10-05 13:48:26 +0200554 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV10)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200555 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun89675492012-10-05 13:48:26 +0200556 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV11)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200557 ssloptions |= SSL_OP_NO_TLSv1_1;
Emeric Brun89675492012-10-05 13:48:26 +0200558 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV12)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200559 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun89675492012-10-05 13:48:26 +0200560 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
Emeric Brun2d0c4822012-10-02 13:45:20 +0200561 ssloptions |= SSL_OP_NO_TICKET;
Emeric Brun2cb7ae52012-10-05 14:14:21 +0200562 if (bind_conf->ssl_options & BC_SSL_O_USE_SSLV3)
563 SSL_CTX_set_ssl_version(ctx, SSLv3_server_method());
564 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV10)
565 SSL_CTX_set_ssl_version(ctx, TLSv1_server_method());
566#if SSL_OP_NO_TLSv1_1
567 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV11)
568 SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method());
569#endif
570#if SSL_OP_NO_TLSv1_2
571 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV12)
572 SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method());
573#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200574
575 SSL_CTX_set_options(ctx, ssloptions);
576 SSL_CTX_set_mode(ctx, sslmode);
Emeric Brune64aef12012-09-21 13:15:06 +0200577 SSL_CTX_set_verify(ctx, bind_conf->verify ? bind_conf->verify : SSL_VERIFY_NONE, ssl_sock_verifycbk);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200578 if (bind_conf->verify & SSL_VERIFY_PEER) {
Emeric Brunfb510ea2012-10-05 12:00:26 +0200579 if (bind_conf->ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200580 /* load CAfile to verify */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200581 if (!SSL_CTX_load_verify_locations(ctx, bind_conf->ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200582 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200583 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200584 cfgerr++;
585 }
586 /* set CA names fo client cert request, function returns void */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200587 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(bind_conf->ca_file));
Emeric Brund94b3fe2012-09-20 18:23:56 +0200588 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200589#ifdef X509_V_FLAG_CRL_CHECK
Emeric Brunfb510ea2012-10-05 12:00:26 +0200590 if (bind_conf->crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200591 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
592
Emeric Brunfb510ea2012-10-05 12:00:26 +0200593 if (!store || !X509_STORE_load_locations(store, bind_conf->crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200594 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200595 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200596 cfgerr++;
597 }
Emeric Brun561e5742012-10-02 15:20:55 +0200598 else {
599 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
600 }
Emeric Brund94b3fe2012-09-20 18:23:56 +0200601 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200602#endif
Emeric Brun644cde02012-12-14 11:21:13 +0100603 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +0200604 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200605
Emeric Brun4f65bff2012-11-16 15:11:00 +0100606 if (global.tune.ssllifetime)
607 SSL_CTX_set_timeout(ctx, global.tune.ssllifetime);
608
Emeric Brunfc0421f2012-09-07 17:30:07 +0200609 shared_context_set_cache(ctx);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200610 if (bind_conf->ciphers &&
611 !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200612 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 +0200613 curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200614 cfgerr++;
615 }
616
617 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200618#ifdef OPENSSL_NPN_NEGOTIATED
619 if (bind_conf->npn_str)
620 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
621#endif
622
Emeric Brunfc0421f2012-09-07 17:30:07 +0200623#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
624 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200625 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200626#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200627#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
628 if (bind_conf->ecdhe) {
629 int i;
630 EC_KEY *ecdh;
631
632 i = OBJ_sn2nid(bind_conf->ecdhe);
633 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
634 Alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
635 curproxy->id, bind_conf->ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
636 cfgerr++;
637 }
638 else {
639 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
640 EC_KEY_free(ecdh);
641 }
642 }
643#endif
644
Emeric Brunfc0421f2012-09-07 17:30:07 +0200645 return cfgerr;
646}
647
Emeric Brun94324a42012-10-11 14:00:19 +0200648/* prepare ssl context from servers options. Returns an error count */
649int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
650{
651 int cfgerr = 0;
652 int options =
653 SSL_OP_ALL | /* all known workarounds for bugs */
654 SSL_OP_NO_SSLv2 |
655 SSL_OP_NO_COMPRESSION;
656 int mode =
657 SSL_MODE_ENABLE_PARTIAL_WRITE |
658 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
659 SSL_MODE_RELEASE_BUFFERS;
660
Thierry Fournier383085f2013-01-24 14:15:43 +0100661 /* Make sure openssl opens /dev/urandom before the chroot */
662 if (!ssl_initialize_random()) {
663 Alert("OpenSSL random data generator initialization failed.\n");
664 cfgerr++;
665 }
666
Emeric Brun94324a42012-10-11 14:00:19 +0200667 /* Initiate SSL context for current server */
668 srv->ssl_ctx.reused_sess = NULL;
669 if (srv->use_ssl)
670 srv->xprt = &ssl_sock;
671 if (srv->check.use_ssl)
672 srv->check.xprt = &ssl_sock;
673
674 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
675 if (!srv->ssl_ctx.ctx) {
676 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
677 proxy_type_str(curproxy), curproxy->id,
678 srv->id);
679 cfgerr++;
680 return cfgerr;
681 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200682 if (srv->ssl_ctx.client_crt) {
683 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
684 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
685 proxy_type_str(curproxy), curproxy->id,
686 srv->id, srv->ssl_ctx.client_crt);
687 cfgerr++;
688 }
689 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
690 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
691 proxy_type_str(curproxy), curproxy->id,
692 srv->id, srv->ssl_ctx.client_crt);
693 cfgerr++;
694 }
695 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
696 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
697 proxy_type_str(curproxy), curproxy->id,
698 srv->id, srv->ssl_ctx.client_crt);
699 cfgerr++;
700 }
701 }
Emeric Brun94324a42012-10-11 14:00:19 +0200702
703 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
704 options |= SSL_OP_NO_SSLv3;
705 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
706 options |= SSL_OP_NO_TLSv1;
707 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
708 options |= SSL_OP_NO_TLSv1_1;
709 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
710 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200711 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
712 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200713 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
714 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
715 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
716 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
717#if SSL_OP_NO_TLSv1_1
718 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
719 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
720#endif
721#if SSL_OP_NO_TLSv1_2
722 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
723 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
724#endif
725
726 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
727 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Emeric Brunef42d922012-10-11 16:11:36 +0200728 SSL_CTX_set_verify(srv->ssl_ctx.ctx, srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE, NULL);
729 if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
730 if (srv->ssl_ctx.ca_file) {
731 /* load CAfile to verify */
732 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
733 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
734 curproxy->id, srv->id,
735 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
736 cfgerr++;
737 }
738 }
739#ifdef X509_V_FLAG_CRL_CHECK
740 if (srv->ssl_ctx.crl_file) {
741 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
742
743 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
744 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
745 curproxy->id, srv->id,
746 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
747 cfgerr++;
748 }
749 else {
750 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
751 }
752 }
753#endif
754 }
755
Emeric Brun4f65bff2012-11-16 15:11:00 +0100756 if (global.tune.ssllifetime)
757 SSL_CTX_set_timeout(srv->ssl_ctx.ctx, global.tune.ssllifetime);
758
Emeric Brun94324a42012-10-11 14:00:19 +0200759 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
760 if (srv->ssl_ctx.ciphers &&
761 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
762 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
763 curproxy->id, srv->id,
764 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
765 cfgerr++;
766 }
767
768 return cfgerr;
769}
770
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200771/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200772 * be NULL, in which case nothing is done. Returns the number of errors
773 * encountered.
774 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200775int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200776{
777 struct ebmb_node *node;
778 struct sni_ctx *sni;
779 int err = 0;
780
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200781 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200782 return 0;
783
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200784 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200785 while (node) {
786 sni = ebmb_entry(node, struct sni_ctx, name);
787 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200788 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200789 node = ebmb_next(node);
790 }
791
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200792 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200793 while (node) {
794 sni = ebmb_entry(node, struct sni_ctx, name);
795 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200796 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200797 node = ebmb_next(node);
798 }
799 return err;
800}
801
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200802/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200803 * be NULL, in which case nothing is done. The default_ctx is nullified too.
804 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200805void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200806{
807 struct ebmb_node *node, *back;
808 struct sni_ctx *sni;
809
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200810 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200811 return;
812
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200813 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200814 while (node) {
815 sni = ebmb_entry(node, struct sni_ctx, name);
816 back = ebmb_next(node);
817 ebmb_delete(node);
818 if (!sni->order) /* only free the CTX on its first occurrence */
819 SSL_CTX_free(sni->ctx);
820 free(sni);
821 node = back;
822 }
823
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200824 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200825 while (node) {
826 sni = ebmb_entry(node, struct sni_ctx, name);
827 back = ebmb_next(node);
828 ebmb_delete(node);
829 if (!sni->order) /* only free the CTX on its first occurrence */
830 SSL_CTX_free(sni->ctx);
831 free(sni);
832 node = back;
833 }
834
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200835 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +0200836}
837
Emeric Brun46591952012-05-18 15:47:34 +0200838/*
839 * This function is called if SSL * context is not yet allocated. The function
840 * is designed to be called before any other data-layer operation and sets the
841 * handshake flag on the connection. It is safe to call it multiple times.
842 * It returns 0 on success and -1 in error case.
843 */
844static int ssl_sock_init(struct connection *conn)
845{
846 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200847 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200848 return 0;
849
Willy Tarreau20879a02012-12-03 16:32:10 +0100850 if (global.maxsslconn && sslconns >= global.maxsslconn) {
851 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +0200852 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100853 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200854
Emeric Brun46591952012-05-18 15:47:34 +0200855 /* If it is in client mode initiate SSL session
856 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100857 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200858 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100859 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +0100860 if (!conn->xprt_ctx) {
861 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +0200862 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100863 }
Emeric Brun46591952012-05-18 15:47:34 +0200864
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200865 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100866 if (objt_server(conn->target)->ssl_ctx.reused_sess)
867 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +0200868
869 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200870 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200871
872 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200873 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200874
875 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200876 return 0;
877 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100878 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200879 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100880 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +0100881 if (!conn->xprt_ctx) {
882 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +0200883 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100884 }
Emeric Brun46591952012-05-18 15:47:34 +0200885
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200886 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200887
888 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200889 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200890
Emeric Brune1f38db2012-09-03 20:36:47 +0200891 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200892 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +0200893
Emeric Brun46591952012-05-18 15:47:34 +0200894 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200895 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200896
897 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200898 return 0;
899 }
900 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +0100901 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +0200902 return -1;
903}
904
905
906/* This is the callback which is used when an SSL handshake is pending. It
907 * updates the FD status if it wants some polling before being called again.
908 * It returns 0 if it fails in a fatal way or needs to poll to go further,
909 * otherwise it returns non-zero and removes itself from the connection's
910 * flags (the bit is provided in <flag> by the caller).
911 */
912int ssl_sock_handshake(struct connection *conn, unsigned int flag)
913{
914 int ret;
915
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200916 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200917 goto out_error;
918
Emeric Brun674b7432012-11-08 19:21:55 +0100919 /* If we use SSL_do_handshake to process a reneg initiated by
920 * the remote peer, it sometimes returns SSL_ERROR_SSL.
921 * Usually SSL_write and SSL_read are used and process implicitly
922 * the reneg handshake.
923 * Here we use SSL_peek as a workaround for reneg.
924 */
925 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
926 char c;
927
928 ret = SSL_peek(conn->xprt_ctx, &c, 1);
929 if (ret <= 0) {
930 /* handshake may have not been completed, let's find why */
931 ret = SSL_get_error(conn->xprt_ctx, ret);
932 if (ret == SSL_ERROR_WANT_WRITE) {
933 /* SSL handshake needs to write, L4 connection may not be ready */
934 __conn_sock_stop_recv(conn);
935 __conn_sock_poll_send(conn);
936 return 0;
937 }
938 else if (ret == SSL_ERROR_WANT_READ) {
939 /* handshake may have been completed but we have
940 * no more data to read.
941 */
942 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
943 ret = 1;
944 goto reneg_ok;
945 }
946 /* SSL handshake needs to read, L4 connection is ready */
947 if (conn->flags & CO_FL_WAIT_L4_CONN)
948 conn->flags &= ~CO_FL_WAIT_L4_CONN;
949 __conn_sock_stop_send(conn);
950 __conn_sock_poll_recv(conn);
951 return 0;
952 }
953 else if (ret == SSL_ERROR_SYSCALL) {
954 /* if errno is null, then connection was successfully established */
955 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
956 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +0100957 if (!conn->err_code) {
958 if (!((SSL *)conn->xprt_ctx)->packet_length)
959 if (!errno)
960 conn->err_code = CO_ER_SSL_EMPTY;
961 else
962 conn->err_code = CO_ER_SSL_ABORT;
963 else
964 conn->err_code = CO_ER_SSL_HANDSHAKE;
965 }
Emeric Brun674b7432012-11-08 19:21:55 +0100966 goto out_error;
967 }
968 else {
969 /* Fail on all other handshake errors */
970 /* Note: OpenSSL may leave unread bytes in the socket's
971 * buffer, causing an RST to be emitted upon close() on
972 * TCP sockets. We first try to drain possibly pending
973 * data to avoid this as much as possible.
974 */
975 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Willy Tarreau20879a02012-12-03 16:32:10 +0100976 if (!conn->err_code)
977 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +0100978 goto out_error;
979 }
980 }
981 /* read some data: consider handshake completed */
982 goto reneg_ok;
983 }
984
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200985 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200986 if (ret != 1) {
987 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200988 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +0200989
990 if (ret == SSL_ERROR_WANT_WRITE) {
991 /* SSL handshake needs to write, L4 connection may not be ready */
992 __conn_sock_stop_recv(conn);
993 __conn_sock_poll_send(conn);
994 return 0;
995 }
996 else if (ret == SSL_ERROR_WANT_READ) {
997 /* SSL handshake needs to read, L4 connection is ready */
998 if (conn->flags & CO_FL_WAIT_L4_CONN)
999 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1000 __conn_sock_stop_send(conn);
1001 __conn_sock_poll_recv(conn);
1002 return 0;
1003 }
Willy Tarreau89230192012-09-28 20:22:13 +02001004 else if (ret == SSL_ERROR_SYSCALL) {
1005 /* if errno is null, then connection was successfully established */
1006 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1007 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001008
1009 if (!((SSL *)conn->xprt_ctx)->packet_length)
1010 if (!errno)
1011 conn->err_code = CO_ER_SSL_EMPTY;
1012 else
1013 conn->err_code = CO_ER_SSL_ABORT;
1014 else
1015 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +02001016 goto out_error;
1017 }
Emeric Brun46591952012-05-18 15:47:34 +02001018 else {
1019 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02001020 /* Note: OpenSSL may leave unread bytes in the socket's
1021 * buffer, causing an RST to be emitted upon close() on
1022 * TCP sockets. We first try to drain possibly pending
1023 * data to avoid this as much as possible.
1024 */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01001025 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Willy Tarreau20879a02012-12-03 16:32:10 +01001026 if (!conn->err_code)
1027 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001028 goto out_error;
1029 }
1030 }
1031
Emeric Brun674b7432012-11-08 19:21:55 +01001032reneg_ok:
1033
Emeric Brun46591952012-05-18 15:47:34 +02001034 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001035 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001036 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +02001037 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001038 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1039 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001040
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001041 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001042 }
1043 }
1044
1045 /* The connection is now established at both layers, it's time to leave */
1046 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1047 return 1;
1048
1049 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001050 /* Clear openssl global errors stack */
1051 ERR_clear_error();
1052
Emeric Brun9fa89732012-10-04 17:09:56 +02001053 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001054 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1055 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1056 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001057 }
1058
Emeric Brun46591952012-05-18 15:47:34 +02001059 /* Fail on all other handshake errors */
1060 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001061 if (!conn->err_code)
1062 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001063 return 0;
1064}
1065
1066/* Receive up to <count> bytes from connection <conn>'s socket and store them
1067 * into buffer <buf>. The caller must ensure that <count> is always smaller
1068 * than the buffer's size. Only one call to recv() is performed, unless the
1069 * buffer wraps, in which case a second call may be performed. The connection's
1070 * flags are updated with whatever special event is detected (error, read0,
1071 * empty). The caller is responsible for taking care of those events and
1072 * avoiding the call if inappropriate. The function does not call the
1073 * connection's polling update function, so the caller is responsible for this.
1074 */
1075static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1076{
1077 int ret, done = 0;
1078 int try = count;
1079
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001080 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001081 goto out_error;
1082
1083 if (conn->flags & CO_FL_HANDSHAKE)
1084 /* a handshake was requested */
1085 return 0;
1086
1087 /* compute the maximum block size we can read at once. */
1088 if (buffer_empty(buf)) {
1089 /* let's realign the buffer to optimize I/O */
1090 buf->p = buf->data;
1091 }
1092 else if (buf->data + buf->o < buf->p &&
1093 buf->p + buf->i < buf->data + buf->size) {
1094 /* remaining space wraps at the end, with a moving limit */
1095 if (try > buf->data + buf->size - (buf->p + buf->i))
1096 try = buf->data + buf->size - (buf->p + buf->i);
1097 }
1098
1099 /* read the largest possible block. For this, we perform only one call
1100 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1101 * in which case we accept to do it once again. A new attempt is made on
1102 * EINTR too.
1103 */
1104 while (try) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001105 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001106 if (conn->flags & CO_FL_ERROR) {
1107 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001108 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001109 }
Emeric Brun46591952012-05-18 15:47:34 +02001110 if (ret > 0) {
1111 buf->i += ret;
1112 done += ret;
1113 if (ret < try)
1114 break;
1115 count -= ret;
1116 try = count;
1117 }
1118 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001119 ret = SSL_get_error(conn->xprt_ctx, ret);
1120 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001121 /* error on protocol or underlying transport */
1122 if ((ret != SSL_ERROR_SYSCALL)
1123 || (errno && (errno != EAGAIN)))
1124 conn->flags |= CO_FL_ERROR;
1125
Emeric Brun644cde02012-12-14 11:21:13 +01001126 /* Clear openssl global errors stack */
1127 ERR_clear_error();
1128 }
Emeric Brun46591952012-05-18 15:47:34 +02001129 goto read0;
1130 }
1131 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001132 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001133 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001134 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001135 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001136 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001137 break;
1138 }
1139 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001140 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1141 /* handshake is running, and it may need to re-enable read */
1142 conn->flags |= CO_FL_SSL_WAIT_HS;
1143 __conn_sock_want_recv(conn);
1144 break;
1145 }
Emeric Brun46591952012-05-18 15:47:34 +02001146 /* we need to poll for retry a read later */
1147 __conn_data_poll_recv(conn);
1148 break;
1149 }
1150 /* otherwise it's a real error */
1151 goto out_error;
1152 }
1153 }
1154 return done;
1155
1156 read0:
1157 conn_sock_read0(conn);
1158 return done;
1159 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001160 /* Clear openssl global errors stack */
1161 ERR_clear_error();
1162
Emeric Brun46591952012-05-18 15:47:34 +02001163 conn->flags |= CO_FL_ERROR;
1164 return done;
1165}
1166
1167
1168/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1169 * <flags> may contain MSG_MORE to make the system hold on without sending
1170 * data too fast, but this flag is ignored at the moment.
1171 * Only one call to send() is performed, unless the buffer wraps, in which case
1172 * a second call may be performed. The connection's flags are updated with
1173 * whatever special event is detected (error, empty). The caller is responsible
1174 * for taking care of those events and avoiding the call if inappropriate. The
1175 * function does not call the connection's polling update function, so the caller
1176 * is responsible for this.
1177 */
1178static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1179{
1180 int ret, try, done;
1181
1182 done = 0;
1183
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001184 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001185 goto out_error;
1186
1187 if (conn->flags & CO_FL_HANDSHAKE)
1188 /* a handshake was requested */
1189 return 0;
1190
1191 /* send the largest possible block. For this we perform only one call
1192 * to send() unless the buffer wraps and we exactly fill the first hunk,
1193 * in which case we accept to do it once again.
1194 */
1195 while (buf->o) {
1196 try = buf->o;
Willy Tarreaubfd59462013-02-21 07:46:09 +01001197
1198 if (global.tune.ssl_max_record && try > global.tune.ssl_max_record)
1199 try = global.tune.ssl_max_record;
1200
Emeric Brun46591952012-05-18 15:47:34 +02001201 /* outgoing data may wrap at the end */
1202 if (buf->data + try > buf->p)
1203 try = buf->data + try - buf->p;
1204
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001205 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001206 if (conn->flags & CO_FL_ERROR) {
1207 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001208 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001209 }
Emeric Brun46591952012-05-18 15:47:34 +02001210 if (ret > 0) {
1211 buf->o -= ret;
1212 done += ret;
1213
Willy Tarreau5fb38032012-12-16 19:39:09 +01001214 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001215 /* optimize data alignment in the buffer */
1216 buf->p = buf->data;
1217
1218 /* if the system buffer is full, don't insist */
1219 if (ret < try)
1220 break;
1221 }
1222 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001223 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001224 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001225 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1226 /* handshake is running, and it may need to re-enable write */
1227 conn->flags |= CO_FL_SSL_WAIT_HS;
1228 __conn_sock_want_send(conn);
1229 break;
1230 }
Emeric Brun46591952012-05-18 15:47:34 +02001231 /* we need to poll to retry a write later */
1232 __conn_data_poll_send(conn);
1233 break;
1234 }
1235 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001236 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001237 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001238 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001239 break;
1240 }
1241 goto out_error;
1242 }
1243 }
1244 return done;
1245
1246 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001247 /* Clear openssl global errors stack */
1248 ERR_clear_error();
1249
Emeric Brun46591952012-05-18 15:47:34 +02001250 conn->flags |= CO_FL_ERROR;
1251 return done;
1252}
1253
Emeric Brun46591952012-05-18 15:47:34 +02001254static void ssl_sock_close(struct connection *conn) {
1255
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001256 if (conn->xprt_ctx) {
1257 SSL_free(conn->xprt_ctx);
1258 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001259 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001260 }
Emeric Brun46591952012-05-18 15:47:34 +02001261}
1262
1263/* This function tries to perform a clean shutdown on an SSL connection, and in
1264 * any case, flags the connection as reusable if no handshake was in progress.
1265 */
1266static void ssl_sock_shutw(struct connection *conn, int clean)
1267{
1268 if (conn->flags & CO_FL_HANDSHAKE)
1269 return;
1270 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001271 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1272 /* Clear openssl global errors stack */
1273 ERR_clear_error();
1274 }
Emeric Brun46591952012-05-18 15:47:34 +02001275
1276 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001277 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001278}
1279
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001280/* used for logging, may be changed for a sample fetch later */
1281const char *ssl_sock_get_cipher_name(struct connection *conn)
1282{
1283 if (!conn->xprt && !conn->xprt_ctx)
1284 return NULL;
1285 return SSL_get_cipher_name(conn->xprt_ctx);
1286}
1287
1288/* used for logging, may be changed for a sample fetch later */
1289const char *ssl_sock_get_proto_version(struct connection *conn)
1290{
1291 if (!conn->xprt && !conn->xprt_ctx)
1292 return NULL;
1293 return SSL_get_version(conn->xprt_ctx);
1294}
1295
Willy Tarreau8d598402012-10-22 17:58:39 +02001296/* Extract a serial from a cert, and copy it to a chunk.
1297 * Returns 1 if serial is found and copied, 0 if no serial found and
1298 * -1 if output is not large enough.
1299 */
1300static int
1301ssl_sock_get_serial(X509 *crt, struct chunk *out)
1302{
1303 ASN1_INTEGER *serial;
1304
1305 serial = X509_get_serialNumber(crt);
1306 if (!serial)
1307 return 0;
1308
1309 if (out->size < serial->length)
1310 return -1;
1311
1312 memcpy(out->str, serial->data, serial->length);
1313 out->len = serial->length;
1314 return 1;
1315}
1316
Emeric Brunce5ad802012-10-22 14:11:22 +02001317
1318/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1319 * Returns 1 if serial is found and copied, 0 if no valid time found
1320 * and -1 if output is not large enough.
1321 */
1322static int
1323ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1324{
1325 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1326 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1327
1328 if (gentm->length < 12)
1329 return 0;
1330 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1331 return 0;
1332 if (out->size < gentm->length-2)
1333 return -1;
1334
1335 memcpy(out->str, gentm->data+2, gentm->length-2);
1336 out->len = gentm->length-2;
1337 return 1;
1338 }
1339 else if (tm->type == V_ASN1_UTCTIME) {
1340 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1341
1342 if (utctm->length < 10)
1343 return 0;
1344 if (utctm->data[0] >= 0x35)
1345 return 0;
1346 if (out->size < utctm->length)
1347 return -1;
1348
1349 memcpy(out->str, utctm->data, utctm->length);
1350 out->len = utctm->length;
1351 return 1;
1352 }
1353
1354 return 0;
1355}
1356
Emeric Brun87855892012-10-17 17:39:35 +02001357/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1358 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1359 */
1360static int
1361ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1362{
1363 X509_NAME_ENTRY *ne;
1364 int i, j, n;
1365 int cur = 0;
1366 const char *s;
1367 char tmp[128];
1368
1369 out->len = 0;
1370 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1371 if (pos < 0)
1372 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1373 else
1374 j = i;
1375
1376 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1377 n = OBJ_obj2nid(ne->object);
1378 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1379 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1380 s = tmp;
1381 }
1382
1383 if (chunk_strcasecmp(entry, s) != 0)
1384 continue;
1385
1386 if (pos < 0)
1387 cur--;
1388 else
1389 cur++;
1390
1391 if (cur != pos)
1392 continue;
1393
1394 if (ne->value->length > out->size)
1395 return -1;
1396
1397 memcpy(out->str, ne->value->data, ne->value->length);
1398 out->len = ne->value->length;
1399 return 1;
1400 }
1401
1402 return 0;
1403
1404}
1405
1406/* Extract and format full DN from a X509_NAME and copy result into a chunk
1407 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1408 */
1409static int
1410ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1411{
1412 X509_NAME_ENTRY *ne;
1413 int i, n, ln;
1414 int l = 0;
1415 const char *s;
1416 char *p;
1417 char tmp[128];
1418
1419 out->len = 0;
1420 p = out->str;
1421 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1422 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1423 n = OBJ_obj2nid(ne->object);
1424 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1425 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1426 s = tmp;
1427 }
1428 ln = strlen(s);
1429
1430 l += 1 + ln + 1 + ne->value->length;
1431 if (l > out->size)
1432 return -1;
1433 out->len = l;
1434
1435 *(p++)='/';
1436 memcpy(p, s, ln);
1437 p += ln;
1438 *(p++)='=';
1439 memcpy(p, ne->value->data, ne->value->length);
1440 p += ne->value->length;
1441 }
1442
1443 if (!out->len)
1444 return 0;
1445
1446 return 1;
1447}
1448
Willy Tarreau7875d092012-09-10 08:20:03 +02001449/***** Below are some sample fetching functions for ACL/patterns *****/
1450
Emeric Brune64aef12012-09-21 13:15:06 +02001451/* boolean, returns true if client cert was present */
1452static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001453smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1454 const struct arg *args, struct sample *smp)
Emeric Brune64aef12012-09-21 13:15:06 +02001455{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001456 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001457 return 0;
1458
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001459 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001460 smp->flags |= SMP_F_MAY_CHANGE;
1461 return 0;
1462 }
1463
1464 smp->flags = 0;
1465 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001466 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001467
1468 return 1;
1469}
1470
Willy Tarreau8d598402012-10-22 17:58:39 +02001471/* bin, returns serial in a binary chunk */
1472static int
1473smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1474 const struct arg *args, struct sample *smp)
1475{
1476 X509 *crt = NULL;
1477 int ret = 0;
1478 struct chunk *smp_trash;
1479
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001480 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001481 return 0;
1482
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001483 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001484 smp->flags |= SMP_F_MAY_CHANGE;
1485 return 0;
1486 }
1487
1488 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001489 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001490 if (!crt)
1491 goto out;
1492
Willy Tarreau47ca5452012-12-23 20:22:19 +01001493 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001494 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1495 goto out;
1496
1497 smp->data.str = *smp_trash;
1498 smp->type = SMP_T_BIN;
1499 ret = 1;
1500out:
1501 if (crt)
1502 X509_free(crt);
1503 return ret;
1504}
Emeric Brune64aef12012-09-21 13:15:06 +02001505
Emeric Brunce5ad802012-10-22 14:11:22 +02001506/*str, returns notafter date in ASN1_UTCTIME format */
1507static int
1508smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1509 const struct arg *args, struct sample *smp)
1510{
1511 X509 *crt = NULL;
1512 int ret = 0;
1513 struct chunk *smp_trash;
1514
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001515 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001516 return 0;
1517
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001518 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001519 smp->flags |= SMP_F_MAY_CHANGE;
1520 return 0;
1521 }
1522
1523 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001524 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001525 if (!crt)
1526 goto out;
1527
Willy Tarreau47ca5452012-12-23 20:22:19 +01001528 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001529 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1530 goto out;
1531
1532 smp->data.str = *smp_trash;
1533 smp->type = SMP_T_STR;
1534 ret = 1;
1535out:
1536 if (crt)
1537 X509_free(crt);
1538 return ret;
1539}
1540
Emeric Brun87855892012-10-17 17:39:35 +02001541/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1542static int
1543smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1544 const struct arg *args, struct sample *smp)
1545{
1546 X509 *crt = NULL;
1547 X509_NAME *name;
1548 int ret = 0;
1549 struct chunk *smp_trash;
1550
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001551 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001552 return 0;
1553
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001554 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001555 smp->flags |= SMP_F_MAY_CHANGE;
1556 return 0;
1557 }
1558
1559 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001560 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001561 if (!crt)
1562 goto out;
1563
1564 name = X509_get_issuer_name(crt);
1565 if (!name)
1566 goto out;
1567
Willy Tarreau47ca5452012-12-23 20:22:19 +01001568 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001569 if (args && args[0].type == ARGT_STR) {
1570 int pos = 1;
1571
1572 if (args[1].type == ARGT_SINT)
1573 pos = args[1].data.sint;
1574 else if (args[1].type == ARGT_UINT)
1575 pos =(int)args[1].data.uint;
1576
1577 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1578 goto out;
1579 }
1580 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1581 goto out;
1582
1583 smp->type = SMP_T_STR;
1584 smp->data.str = *smp_trash;
1585 ret = 1;
1586out:
1587 if (crt)
1588 X509_free(crt);
1589 return ret;
1590}
1591
Emeric Brunce5ad802012-10-22 14:11:22 +02001592/*str, returns notbefore date in ASN1_UTCTIME format */
1593static int
1594smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1595 const struct arg *args, struct sample *smp)
1596{
1597 X509 *crt = NULL;
1598 int ret = 0;
1599 struct chunk *smp_trash;
1600
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001601 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001602 return 0;
1603
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001604 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001605 smp->flags |= SMP_F_MAY_CHANGE;
1606 return 0;
1607 }
1608
1609 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001610 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001611 if (!crt)
1612 goto out;
1613
Willy Tarreau47ca5452012-12-23 20:22:19 +01001614 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001615 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1616 goto out;
1617
1618 smp->data.str = *smp_trash;
1619 smp->type = SMP_T_STR;
1620 ret = 1;
1621out:
1622 if (crt)
1623 X509_free(crt);
1624 return ret;
1625}
1626
Emeric Brun87855892012-10-17 17:39:35 +02001627/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1628static int
1629smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1630 const struct arg *args, struct sample *smp)
1631{
1632 X509 *crt = NULL;
1633 X509_NAME *name;
1634 int ret = 0;
1635 struct chunk *smp_trash;
1636
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001637 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001638 return 0;
1639
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001640 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001641 smp->flags |= SMP_F_MAY_CHANGE;
1642 return 0;
1643 }
1644
1645 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001646 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001647 if (!crt)
1648 goto out;
1649
1650 name = X509_get_subject_name(crt);
1651 if (!name)
1652 goto out;
1653
Willy Tarreau47ca5452012-12-23 20:22:19 +01001654 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001655 if (args && args[0].type == ARGT_STR) {
1656 int pos = 1;
1657
1658 if (args[1].type == ARGT_SINT)
1659 pos = args[1].data.sint;
1660 else if (args[1].type == ARGT_UINT)
1661 pos =(int)args[1].data.uint;
1662
1663 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1664 goto out;
1665 }
1666 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1667 goto out;
1668
1669 smp->type = SMP_T_STR;
1670 smp->data.str = *smp_trash;
1671 ret = 1;
1672out:
1673 if (crt)
1674 X509_free(crt);
1675 return ret;
1676}
Emeric Brun9143d372012-12-20 15:44:16 +01001677
1678/* integer, returns true if current session use a client certificate */
1679static int
1680smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1681 const struct arg *args, struct sample *smp)
1682{
1683 X509 *crt;
1684
1685 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
1686 return 0;
1687
1688 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
1689 smp->flags |= SMP_F_MAY_CHANGE;
1690 return 0;
1691 }
1692
1693 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
1694 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
1695 if (crt) {
1696 X509_free(crt);
1697 }
1698
1699 smp->type = SMP_T_BOOL;
1700 smp->data.uint = (crt != NULL);
1701 return 1;
1702}
1703
Emeric Bruna7359fd2012-10-17 15:03:11 +02001704/* integer, returns the client certificate version */
1705static int
1706smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1707 const struct arg *args, struct sample *smp)
1708{
1709 X509 *crt;
1710
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001711 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001712 return 0;
1713
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001714 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001715 smp->flags |= SMP_F_MAY_CHANGE;
1716 return 0;
1717 }
1718
1719 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001720 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001721 if (!crt)
1722 return 0;
1723
1724 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1725 X509_free(crt);
1726 smp->type = SMP_T_UINT;
1727
1728 return 1;
1729}
1730
Emeric Brun7f56e742012-10-19 18:15:40 +02001731/* str, returns the client certificate sig alg */
1732static int
1733smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1734 const struct arg *args, struct sample *smp)
1735{
1736 X509 *crt;
1737 int nid;
1738
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001739 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02001740 return 0;
1741
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001742 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02001743 smp->flags |= SMP_F_MAY_CHANGE;
1744 return 0;
1745 }
1746
1747 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001748 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02001749 if (!crt)
1750 return 0;
1751
1752 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1753
1754 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1755 if (!smp->data.str.str)
1756 return 0;
1757
1758 smp->type = SMP_T_CSTR;
1759 smp->data.str.len = strlen(smp->data.str.str);
1760 X509_free(crt);
1761
1762 return 1;
1763}
1764
Emeric Brun521a0112012-10-22 12:22:55 +02001765/* str, returns the client certificate key alg */
1766static int
1767smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1768 const struct arg *args, struct sample *smp)
1769{
1770 X509 *crt;
1771 int nid;
1772
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001773 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02001774 return 0;
1775
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001776 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02001777 smp->flags |= SMP_F_MAY_CHANGE;
1778 return 0;
1779 }
1780
1781 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001782 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02001783 if (!crt)
1784 return 0;
1785
1786 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1787
1788 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1789 if (!smp->data.str.str)
1790 return 0;
1791
1792 smp->type = SMP_T_CSTR;
1793 smp->data.str.len = strlen(smp->data.str.str);
1794 X509_free(crt);
1795
1796 return 1;
1797}
1798
Emeric Brun2525b6b2012-10-18 15:59:43 +02001799/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02001800static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001801smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau7875d092012-09-10 08:20:03 +02001802 const struct arg *args, struct sample *smp)
1803{
1804 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001805 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02001806 return 1;
1807}
1808
Emeric Brun2525b6b2012-10-18 15:59:43 +02001809/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02001810static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001811smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1812 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02001813{
1814#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1815 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001816 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock) &&
1817 l4->si[0].conn->xprt_ctx &&
1818 SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02001819 return 1;
1820#else
1821 return 0;
1822#endif
1823}
1824
Willy Tarreau8d598402012-10-22 17:58:39 +02001825/* bin, returns serial in a binary chunk */
1826static int
1827smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1828 const struct arg *args, struct sample *smp)
1829{
1830 X509 *crt = NULL;
1831 int ret = 0;
1832 struct chunk *smp_trash;
1833
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001834 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001835 return 0;
1836
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001837 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001838 smp->flags |= SMP_F_MAY_CHANGE;
1839 return 0;
1840 }
1841
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001842 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001843 if (!crt)
1844 goto out;
1845
Willy Tarreau47ca5452012-12-23 20:22:19 +01001846 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001847 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1848 goto out;
1849
1850 smp->data.str = *smp_trash;
1851 smp->type = SMP_T_BIN;
1852 ret = 1;
1853out:
1854 return ret;
1855}
Emeric Brunce5ad802012-10-22 14:11:22 +02001856/*str, returns notafter date in ASN1_UTCTIME format */
1857static int
1858smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1859 const struct arg *args, struct sample *smp)
1860{
1861 X509 *crt = NULL;
1862 int ret = 0;
1863 struct chunk *smp_trash;
1864
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001865 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001866 return 0;
1867
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001868 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001869 smp->flags |= SMP_F_MAY_CHANGE;
1870 return 0;
1871 }
1872
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001873 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001874 if (!crt)
1875 goto out;
1876
Willy Tarreau47ca5452012-12-23 20:22:19 +01001877 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001878 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1879 goto out;
1880
1881 smp->data.str = *smp_trash;
1882 smp->type = SMP_T_STR;
1883 ret = 1;
1884out:
1885 return ret;
1886}
1887
1888/*str, returns notbefore date in ASN1_UTCTIME format */
1889static int
1890smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1891 const struct arg *args, struct sample *smp)
1892{
1893 X509 *crt = NULL;
1894 int ret = 0;
1895 struct chunk *smp_trash;
1896
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001897 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001898 return 0;
1899
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001900 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001901 smp->flags |= SMP_F_MAY_CHANGE;
1902 return 0;
1903 }
1904
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001905 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001906 if (!crt)
1907 goto out;
1908
Willy Tarreau47ca5452012-12-23 20:22:19 +01001909 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001910 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1911 goto out;
1912
1913 smp->data.str = *smp_trash;
1914 smp->type = SMP_T_STR;
1915 ret = 1;
1916out:
1917 return ret;
1918}
Willy Tarreau8d598402012-10-22 17:58:39 +02001919
Emeric Bruna7359fd2012-10-17 15:03:11 +02001920/* integer, returns the frontend certificate version */
1921static int
1922smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1923 const struct arg *args, struct sample *smp)
1924{
1925 X509 *crt;
1926
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001927 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001928 return 0;
1929
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001930 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001931 smp->flags |= SMP_F_MAY_CHANGE;
1932 return 0;
1933 }
1934
1935 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001936 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001937 if (!crt)
1938 return 0;
1939
1940 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1941 smp->type = SMP_T_UINT;
1942
1943 return 1;
1944}
1945
Emeric Brun7f56e742012-10-19 18:15:40 +02001946/* str, returns the client certificate sig alg */
1947static int
1948smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1949 const struct arg *args, struct sample *smp)
1950{
1951 X509 *crt;
1952 int nid;
1953
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001954 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02001955 return 0;
1956
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001957 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02001958 smp->flags |= SMP_F_MAY_CHANGE;
1959 return 0;
1960 }
1961
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001962 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02001963 if (!crt)
1964 return 0;
1965
1966 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1967
1968 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1969 if (!smp->data.str.str)
1970 return 0;
1971
1972 smp->type = SMP_T_CSTR;
1973 smp->data.str.len = strlen(smp->data.str.str);
1974
1975 return 1;
1976}
1977
Emeric Brun521a0112012-10-22 12:22:55 +02001978/* str, returns the client certificate key alg */
1979static int
1980smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1981 const struct arg *args, struct sample *smp)
1982{
1983 X509 *crt;
1984 int nid;
1985
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001986 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02001987 return 0;
1988
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001989 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02001990 smp->flags |= SMP_F_MAY_CHANGE;
1991 return 0;
1992 }
1993
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001994 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02001995 if (!crt)
1996 return 0;
1997
1998 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1999
2000 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2001 if (!smp->data.str.str)
2002 return 0;
2003
2004 smp->type = SMP_T_CSTR;
2005 smp->data.str.len = strlen(smp->data.str.str);
2006
2007 return 1;
2008}
2009
Emeric Brun87855892012-10-17 17:39:35 +02002010/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2011static int
2012smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2013 const struct arg *args, struct sample *smp)
2014{
2015 X509 *crt = NULL;
2016 X509_NAME *name;
2017 int ret = 0;
2018 struct chunk *smp_trash;
2019
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002020 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002021 return 0;
2022
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002023 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002024 smp->flags |= SMP_F_MAY_CHANGE;
2025 return 0;
2026 }
2027
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002028 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002029 if (!crt)
2030 goto out;
2031
2032 name = X509_get_issuer_name(crt);
2033 if (!name)
2034 goto out;
2035
Willy Tarreau47ca5452012-12-23 20:22:19 +01002036 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002037 if (args && args[0].type == ARGT_STR) {
2038 int pos = 1;
2039
2040 if (args[1].type == ARGT_SINT)
2041 pos = args[1].data.sint;
2042 else if (args[1].type == ARGT_UINT)
2043 pos =(int)args[1].data.uint;
2044
2045 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2046 goto out;
2047 }
2048 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2049 goto out;
2050
2051 smp->type = SMP_T_STR;
2052 smp->data.str = *smp_trash;
2053 ret = 1;
2054out:
2055 return ret;
2056}
2057
2058/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2059static int
2060smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2061 const struct arg *args, struct sample *smp)
2062{
2063 X509 *crt = NULL;
2064 X509_NAME *name;
2065 int ret = 0;
2066 struct chunk *smp_trash;
2067
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002068 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002069 return 0;
2070
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002071 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002072 smp->flags |= SMP_F_MAY_CHANGE;
2073 return 0;
2074 }
2075
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002076 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002077 if (!crt)
2078 goto out;
2079
2080 name = X509_get_subject_name(crt);
2081 if (!name)
2082 goto out;
2083
Willy Tarreau47ca5452012-12-23 20:22:19 +01002084 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002085 if (args && args[0].type == ARGT_STR) {
2086 int pos = 1;
2087
2088 if (args[1].type == ARGT_SINT)
2089 pos = args[1].data.sint;
2090 else if (args[1].type == ARGT_UINT)
2091 pos =(int)args[1].data.uint;
2092
2093 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2094 goto out;
2095 }
2096 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2097 goto out;
2098
2099 smp->type = SMP_T_STR;
2100 smp->data.str = *smp_trash;
2101 ret = 1;
2102out:
2103 return ret;
2104}
2105
Emeric Brun589fcad2012-10-16 14:13:26 +02002106static int
2107smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2108 const struct arg *args, struct sample *smp)
2109{
2110 smp->flags = 0;
2111
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002112 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002113 return 0;
2114
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002115 smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002116 if (!smp->data.str.str)
2117 return 0;
2118
2119 smp->type = SMP_T_CSTR;
2120 smp->data.str.len = strlen(smp->data.str.str);
2121
2122 return 1;
2123}
2124
2125static int
2126smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2127 const struct arg *args, struct sample *smp)
2128{
2129 smp->flags = 0;
2130
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002131 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002132 return 0;
2133
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002134 if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
Emeric Brun589fcad2012-10-16 14:13:26 +02002135 return 0;
2136
2137 smp->type = SMP_T_UINT;
2138
2139 return 1;
2140}
2141
2142static int
2143smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2144 const struct arg *args, struct sample *smp)
2145{
2146 smp->flags = 0;
2147
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002148 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002149 return 0;
2150
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002151 smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002152 if (!smp->data.uint)
2153 return 0;
2154
2155 smp->type = SMP_T_UINT;
2156
2157 return 1;
2158}
2159
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002160#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002161static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002162smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2163 const struct arg *args, struct sample *smp)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002164{
Willy Tarreaua33c6542012-10-15 13:19:06 +02002165 smp->flags = 0;
2166 smp->type = SMP_T_CSTR;
2167
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002168 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002169 return 0;
2170
2171 smp->data.str.str = NULL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002172 SSL_get0_next_proto_negotiated(l4->si[0].conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002173 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2174
2175 if (!smp->data.str.str)
2176 return 0;
2177
2178 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002179}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002180#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002181
2182static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002183smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2184 const struct arg *args, struct sample *smp)
2185{
2186 smp->flags = 0;
2187
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002188 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002189 return 0;
2190
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002191 smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002192 if (!smp->data.str.str)
2193 return 0;
2194
2195 smp->type = SMP_T_CSTR;
2196 smp->data.str.len = strlen(smp->data.str.str);
2197
2198 return 1;
2199}
2200
2201static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002202smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2203 const struct arg *args, struct sample *smp)
2204{
2205#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2206 SSL_SESSION *sess;
2207
2208 smp->flags = 0;
2209 smp->type = SMP_T_CBIN;
2210
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002211 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunfe68f682012-10-16 14:59:28 +02002212 return 0;
2213
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002214 sess = SSL_get_session(l4->si[0].conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002215 if (!sess)
2216 return 0;
2217
2218 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2219 if (!smp->data.str.str || !&smp->data.str.len)
2220 return 0;
2221
2222 return 1;
2223#else
2224 return 0;
2225#endif
2226}
2227
2228static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002229smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2230 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02002231{
2232#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2233 smp->flags = 0;
2234 smp->type = SMP_T_CSTR;
2235
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002236 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau7875d092012-09-10 08:20:03 +02002237 return 0;
2238
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002239 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 +02002240 if (!smp->data.str.str)
2241 return 0;
2242
Willy Tarreau7875d092012-09-10 08:20:03 +02002243 smp->data.str.len = strlen(smp->data.str.str);
2244 return 1;
2245#else
2246 return 0;
2247#endif
2248}
2249
Emeric Brun2525b6b2012-10-18 15:59:43 +02002250/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002251static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002252smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002253 const struct arg *args, struct sample *smp)
2254{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002255 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002256 return 0;
2257
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002258 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002259 smp->flags = SMP_F_MAY_CHANGE;
2260 return 0;
2261 }
2262
2263 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002264 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002265 smp->flags = 0;
2266
2267 return 1;
2268}
2269
Emeric Brun2525b6b2012-10-18 15:59:43 +02002270/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002271static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002272smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002273 const struct arg *args, struct sample *smp)
2274{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002275 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002276 return 0;
2277
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002278 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002279 smp->flags = SMP_F_MAY_CHANGE;
2280 return 0;
2281 }
2282
2283 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002284 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002285 smp->flags = 0;
2286
2287 return 1;
2288}
2289
Emeric Brun2525b6b2012-10-18 15:59:43 +02002290/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002291static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002292smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2293 const struct arg *args, struct sample *smp)
Emeric Brunf282a812012-09-21 15:27:54 +02002294{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002295 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002296 return 0;
2297
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002298 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002299 smp->flags = SMP_F_MAY_CHANGE;
2300 return 0;
2301 }
2302
2303 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002304 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002305 smp->flags = 0;
2306
2307 return 1;
2308}
2309
Emeric Brun2525b6b2012-10-18 15:59:43 +02002310/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002311static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002312smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2313 const struct arg *args, struct sample *smp)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002314{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002315 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002316 return 0;
2317
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002318 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002319 smp->flags = SMP_F_MAY_CHANGE;
2320 return 0;
2321 }
2322
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002323 if (!l4->si[0].conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002324 return 0;
2325
2326 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002327 smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002328 smp->flags = 0;
2329
2330 return 1;
2331}
2332
Emeric Brunfb510ea2012-10-05 12:00:26 +02002333/* parse the "ca-file" bind keyword */
2334static 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 +02002335{
2336 if (!*args[cur_arg + 1]) {
2337 if (err)
2338 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2339 return ERR_ALERT | ERR_FATAL;
2340 }
2341
Emeric Brunef42d922012-10-11 16:11:36 +02002342 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2343 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2344 else
2345 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002346
Emeric Brund94b3fe2012-09-20 18:23:56 +02002347 return 0;
2348}
2349
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002350/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002351static 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 +02002352{
2353 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002354 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002355 return ERR_ALERT | ERR_FATAL;
2356 }
2357
Emeric Brun76d88952012-10-05 15:47:31 +02002358 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002359 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002360 return 0;
2361}
2362
2363/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002364static 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 +02002365{
Emeric Brunc8e8d122012-10-02 18:42:10 +02002366 char path[PATH_MAX];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002367 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002368 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002369 return ERR_ALERT | ERR_FATAL;
2370 }
2371
Emeric Brunc8e8d122012-10-02 18:42:10 +02002372 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
2373 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > PATH_MAX) {
2374 memprintf(err, "'%s' : path too long", args[cur_arg]);
2375 return ERR_ALERT | ERR_FATAL;
2376 }
2377 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2378 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2379 return ERR_ALERT | ERR_FATAL;
2380
2381 return 0;
2382 }
2383
Willy Tarreau4348fad2012-09-20 16:48:07 +02002384 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002385 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002386
2387 return 0;
2388}
2389
Emeric Brunfb510ea2012-10-05 12:00:26 +02002390/* parse the "crl-file" bind keyword */
2391static 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 +02002392{
Emeric Brun051cdab2012-10-02 19:25:50 +02002393#ifndef X509_V_FLAG_CRL_CHECK
2394 if (err)
2395 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2396 return ERR_ALERT | ERR_FATAL;
2397#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002398 if (!*args[cur_arg + 1]) {
2399 if (err)
2400 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2401 return ERR_ALERT | ERR_FATAL;
2402 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002403
Emeric Brunef42d922012-10-11 16:11:36 +02002404 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2405 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2406 else
2407 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002408
Emeric Brun2b58d042012-09-20 17:10:03 +02002409 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002410#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002411}
2412
2413/* parse the "ecdhe" bind keyword keywords */
2414static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2415{
2416#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2417 if (err)
2418 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2419 return ERR_ALERT | ERR_FATAL;
2420#elif defined(OPENSSL_NO_ECDH)
2421 if (err)
2422 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2423 return ERR_ALERT | ERR_FATAL;
2424#else
2425 if (!*args[cur_arg + 1]) {
2426 if (err)
2427 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2428 return ERR_ALERT | ERR_FATAL;
2429 }
2430
2431 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002432
2433 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002434#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002435}
2436
Emeric Brun81c00f02012-09-21 14:31:21 +02002437/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2438static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2439{
2440 int code;
2441 char *p = args[cur_arg + 1];
2442 unsigned long long *ignerr = &conf->crt_ignerr;
2443
2444 if (!*p) {
2445 if (err)
2446 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2447 return ERR_ALERT | ERR_FATAL;
2448 }
2449
2450 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2451 ignerr = &conf->ca_ignerr;
2452
2453 if (strcmp(p, "all") == 0) {
2454 *ignerr = ~0ULL;
2455 return 0;
2456 }
2457
2458 while (p) {
2459 code = atoi(p);
2460 if ((code <= 0) || (code > 63)) {
2461 if (err)
2462 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2463 args[cur_arg], code, args[cur_arg + 1]);
2464 return ERR_ALERT | ERR_FATAL;
2465 }
2466 *ignerr |= 1ULL << code;
2467 p = strchr(p, ',');
2468 if (p)
2469 p++;
2470 }
2471
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002472 return 0;
2473}
2474
2475/* parse the "force-sslv3" bind keyword */
2476static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2477{
2478 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2479 return 0;
2480}
2481
2482/* parse the "force-tlsv10" bind keyword */
2483static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2484{
2485 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002486 return 0;
2487}
2488
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002489/* parse the "force-tlsv11" bind keyword */
2490static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2491{
2492#if SSL_OP_NO_TLSv1_1
2493 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
2494 return 0;
2495#else
2496 if (err)
2497 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
2498 return ERR_ALERT | ERR_FATAL;
2499#endif
2500}
2501
2502/* parse the "force-tlsv12" bind keyword */
2503static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2504{
2505#if SSL_OP_NO_TLSv1_2
2506 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
2507 return 0;
2508#else
2509 if (err)
2510 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
2511 return ERR_ALERT | ERR_FATAL;
2512#endif
2513}
2514
2515
Emeric Brun2d0c4822012-10-02 13:45:20 +02002516/* parse the "no-tls-tickets" bind keyword */
2517static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2518{
Emeric Brun89675492012-10-05 13:48:26 +02002519 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02002520 return 0;
2521}
2522
Emeric Brun2d0c4822012-10-02 13:45:20 +02002523
Emeric Brun9b3009b2012-10-05 11:55:06 +02002524/* parse the "no-sslv3" bind keyword */
2525static 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 +02002526{
Emeric Brun89675492012-10-05 13:48:26 +02002527 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002528 return 0;
2529}
2530
Emeric Brun9b3009b2012-10-05 11:55:06 +02002531/* parse the "no-tlsv10" bind keyword */
2532static 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 +02002533{
Emeric Brun89675492012-10-05 13:48:26 +02002534 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002535 return 0;
2536}
2537
Emeric Brun9b3009b2012-10-05 11:55:06 +02002538/* parse the "no-tlsv11" bind keyword */
2539static 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 +02002540{
Emeric Brun89675492012-10-05 13:48:26 +02002541 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002542 return 0;
2543}
2544
Emeric Brun9b3009b2012-10-05 11:55:06 +02002545/* parse the "no-tlsv12" bind keyword */
2546static 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 +02002547{
Emeric Brun89675492012-10-05 13:48:26 +02002548 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002549 return 0;
2550}
2551
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002552/* parse the "npn" bind keyword */
2553static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2554{
2555#ifdef OPENSSL_NPN_NEGOTIATED
2556 char *p1, *p2;
2557
2558 if (!*args[cur_arg + 1]) {
2559 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
2560 return ERR_ALERT | ERR_FATAL;
2561 }
2562
2563 free(conf->npn_str);
2564
2565 /* the NPN string is built as a suite of (<len> <name>)* */
2566 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
2567 conf->npn_str = calloc(1, conf->npn_len);
2568 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
2569
2570 /* replace commas with the name length */
2571 p1 = conf->npn_str;
2572 p2 = p1 + 1;
2573 while (1) {
2574 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
2575 if (!p2)
2576 p2 = p1 + 1 + strlen(p1 + 1);
2577
2578 if (p2 - (p1 + 1) > 255) {
2579 *p2 = '\0';
2580 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2581 return ERR_ALERT | ERR_FATAL;
2582 }
2583
2584 *p1 = p2 - (p1 + 1);
2585 p1 = p2;
2586
2587 if (!*p2)
2588 break;
2589
2590 *(p2++) = '\0';
2591 }
2592 return 0;
2593#else
2594 if (err)
2595 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
2596 return ERR_ALERT | ERR_FATAL;
2597#endif
2598}
2599
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002600/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002601static 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 +02002602{
Willy Tarreau81796be2012-09-22 19:11:47 +02002603 struct listener *l;
2604
Willy Tarreau4348fad2012-09-20 16:48:07 +02002605 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02002606
2607 if (global.listen_default_ciphers && !conf->ciphers)
2608 conf->ciphers = strdup(global.listen_default_ciphers);
2609
Willy Tarreau81796be2012-09-22 19:11:47 +02002610 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002611 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02002612
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002613 return 0;
2614}
2615
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002616/* parse the "strict-sni" bind keyword */
2617static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2618{
2619 conf->strict_sni = 1;
2620 return 0;
2621}
2622
Emeric Brund94b3fe2012-09-20 18:23:56 +02002623/* parse the "verify" bind keyword */
2624static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2625{
2626 if (!*args[cur_arg + 1]) {
2627 if (err)
2628 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
2629 return ERR_ALERT | ERR_FATAL;
2630 }
2631
2632 if (strcmp(args[cur_arg + 1], "none") == 0)
2633 conf->verify = SSL_VERIFY_NONE;
2634 else if (strcmp(args[cur_arg + 1], "optional") == 0)
2635 conf->verify = SSL_VERIFY_PEER;
2636 else if (strcmp(args[cur_arg + 1], "required") == 0)
2637 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2638 else {
2639 if (err)
2640 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
2641 args[cur_arg], args[cur_arg + 1]);
2642 return ERR_ALERT | ERR_FATAL;
2643 }
2644
2645 return 0;
2646}
2647
Willy Tarreau92faadf2012-10-10 23:04:25 +02002648/************** "server" keywords ****************/
2649
Emeric Brunef42d922012-10-11 16:11:36 +02002650/* parse the "ca-file" server keyword */
2651static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2652{
2653 if (!*args[*cur_arg + 1]) {
2654 if (err)
2655 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
2656 return ERR_ALERT | ERR_FATAL;
2657 }
2658
2659 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2660 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2661 else
2662 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
2663
2664 return 0;
2665}
2666
Willy Tarreau92faadf2012-10-10 23:04:25 +02002667/* parse the "check-ssl" server keyword */
2668static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2669{
2670 newsrv->check.use_ssl = 1;
2671 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2672 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2673 return 0;
2674}
2675
2676/* parse the "ciphers" server keyword */
2677static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2678{
2679 if (!*args[*cur_arg + 1]) {
2680 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
2681 return ERR_ALERT | ERR_FATAL;
2682 }
2683
2684 free(newsrv->ssl_ctx.ciphers);
2685 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
2686 return 0;
2687}
2688
Emeric Brunef42d922012-10-11 16:11:36 +02002689/* parse the "crl-file" server keyword */
2690static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2691{
2692#ifndef X509_V_FLAG_CRL_CHECK
2693 if (err)
2694 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
2695 return ERR_ALERT | ERR_FATAL;
2696#else
2697 if (!*args[*cur_arg + 1]) {
2698 if (err)
2699 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
2700 return ERR_ALERT | ERR_FATAL;
2701 }
2702
2703 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2704 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2705 else
2706 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
2707
2708 return 0;
2709#endif
2710}
2711
Emeric Bruna7aa3092012-10-26 12:58:00 +02002712/* parse the "crt" server keyword */
2713static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2714{
2715 if (!*args[*cur_arg + 1]) {
2716 if (err)
2717 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
2718 return ERR_ALERT | ERR_FATAL;
2719 }
2720
2721 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
2722 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2723 else
2724 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
2725
2726 return 0;
2727}
Emeric Brunef42d922012-10-11 16:11:36 +02002728
Willy Tarreau92faadf2012-10-10 23:04:25 +02002729/* parse the "force-sslv3" server keyword */
2730static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2731{
2732 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
2733 return 0;
2734}
2735
2736/* parse the "force-tlsv10" server keyword */
2737static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2738{
2739 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
2740 return 0;
2741}
2742
2743/* parse the "force-tlsv11" server keyword */
2744static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2745{
2746#if SSL_OP_NO_TLSv1_1
2747 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
2748 return 0;
2749#else
2750 if (err)
2751 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
2752 return ERR_ALERT | ERR_FATAL;
2753#endif
2754}
2755
2756/* parse the "force-tlsv12" server keyword */
2757static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2758{
2759#if SSL_OP_NO_TLSv1_2
2760 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
2761 return 0;
2762#else
2763 if (err)
2764 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
2765 return ERR_ALERT | ERR_FATAL;
2766#endif
2767}
2768
2769/* parse the "no-sslv3" server keyword */
2770static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2771{
2772 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
2773 return 0;
2774}
2775
2776/* parse the "no-tlsv10" server keyword */
2777static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2778{
2779 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
2780 return 0;
2781}
2782
2783/* parse the "no-tlsv11" server keyword */
2784static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2785{
2786 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
2787 return 0;
2788}
2789
2790/* parse the "no-tlsv12" server keyword */
2791static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2792{
2793 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
2794 return 0;
2795}
2796
Emeric Brunf9c5c472012-10-11 15:28:34 +02002797/* parse the "no-tls-tickets" server keyword */
2798static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2799{
2800 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
2801 return 0;
2802}
2803
Willy Tarreau92faadf2012-10-10 23:04:25 +02002804/* parse the "ssl" server keyword */
2805static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2806{
2807 newsrv->use_ssl = 1;
2808 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2809 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2810 return 0;
2811}
2812
Emeric Brunef42d922012-10-11 16:11:36 +02002813/* parse the "verify" server keyword */
2814static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2815{
2816 if (!*args[*cur_arg + 1]) {
2817 if (err)
2818 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
2819 return ERR_ALERT | ERR_FATAL;
2820 }
2821
2822 if (strcmp(args[*cur_arg + 1], "none") == 0)
2823 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
2824 else if (strcmp(args[*cur_arg + 1], "required") == 0)
2825 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
2826 else {
2827 if (err)
2828 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
2829 args[*cur_arg], args[*cur_arg + 1]);
2830 return ERR_ALERT | ERR_FATAL;
2831 }
2832
2833 return 0;
2834}
2835
Willy Tarreau7875d092012-09-10 08:20:03 +02002836/* Note: must not be declared <const> as its list will be overwritten.
2837 * Please take care of keeping this list alphabetically sorted.
2838 */
2839static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
Emeric Brun2525b6b2012-10-18 15:59:43 +02002840 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2841 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2842 { "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 +02002843 { "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 +02002844 { "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 +02002845 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
2846 { "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 +02002847 { "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 +02002848 { "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 +02002849 { "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 +01002850 { "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 +02002851 { "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 +02002852 { "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 +02002853 { "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 +02002854 { "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 +02002855 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
2856 { "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 +02002857 { "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 +02002858 { "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 +02002859 { "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 +02002860 { "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 +02002861 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun589fcad2012-10-16 14:13:26 +02002862 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2863 { "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 +02002864 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
2865 { "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 +02002866#ifdef OPENSSL_NPN_NEGOTIATED
Emeric Brun2525b6b2012-10-18 15:59:43 +02002867 { "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 +02002868#endif
Emeric Brun589fcad2012-10-16 14:13:26 +02002869 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
2870 { "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 +02002871 { "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 +02002872 { "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 +02002873 { NULL, NULL, 0, 0, 0 },
2874}};
2875
2876/* Note: must not be declared <const> as its list will be overwritten.
2877 * Please take care of keeping this list alphabetically sorted.
2878 */
2879static struct acl_kw_list acl_kws = {{ },{
Emeric Brun2525b6b2012-10-18 15:59:43 +02002880 { "ssl_c_ca_err", acl_parse_int, smp_fetch_ssl_c_ca_err, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2881 { "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 },
2882 { "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 +02002883 { "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 +02002884 { "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 +02002885 { "ssl_c_notafter", acl_parse_str, smp_fetch_ssl_c_notafter, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2886 { "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 +02002887 { "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 +02002888 { "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 +02002889 { "ssl_c_serial", acl_parse_bin, smp_fetch_ssl_c_serial, acl_match_bin, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun9143d372012-12-20 15:44:16 +01002890 { "ssl_c_used", acl_parse_int, smp_fetch_ssl_c_used, acl_match_nothing, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002891 { "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 +02002892 { "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 +02002893 { "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 +02002894 { "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 +02002895 { "ssl_f_notafter", acl_parse_str, smp_fetch_ssl_f_notafter, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2896 { "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 +02002897 { "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 +02002898 { "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 +02002899 { "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 +02002900 { "ssl_f_version", acl_parse_int, smp_fetch_ssl_f_version, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002901 { "ssl_fc", acl_parse_int, smp_fetch_ssl_fc, acl_match_nothing, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun589fcad2012-10-16 14:13:26 +02002902 { "ssl_fc_alg_keysize", acl_parse_str, smp_fetch_ssl_fc_alg_keysize, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2903 { "ssl_fc_cipher", acl_parse_str, smp_fetch_ssl_fc_cipher, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002904 { "ssl_fc_has_crt", acl_parse_int, smp_fetch_ssl_fc_has_crt, acl_match_nothing, ACL_USE_L6REQ_PERMANENT, 0 },
2905 { "ssl_fc_has_sni", acl_parse_int, smp_fetch_ssl_fc_has_sni, acl_match_nothing, ACL_USE_L6REQ_PERMANENT, 0 },
Willy Tarreaua33c6542012-10-15 13:19:06 +02002906#ifdef OPENSSL_NPN_NEGOTIATED
Emeric Brun2525b6b2012-10-18 15:59:43 +02002907 { "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 +02002908#endif
Emeric Brun589fcad2012-10-16 14:13:26 +02002909 { "ssl_fc_protocol", acl_parse_str, smp_fetch_ssl_fc_protocol, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2910 { "ssl_fc_use_keysize", acl_parse_str, smp_fetch_ssl_fc_use_keysize, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002911 { "ssl_fc_sni", acl_parse_str, smp_fetch_ssl_fc_sni, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2912 { "ssl_fc_sni_end", acl_parse_str, smp_fetch_ssl_fc_sni, acl_match_end, ACL_USE_L6REQ_PERMANENT, 0 },
2913 { "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 +02002914 { NULL, NULL, NULL, NULL },
2915}};
2916
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002917/* Note: must not be declared <const> as its list will be overwritten.
2918 * Please take care of keeping this list alphabetically sorted, doing so helps
2919 * all code contributors.
2920 * Optional keywords are also declared with a NULL ->parse() function so that
2921 * the config parser can report an appropriate error when a known keyword was
2922 * not enabled.
2923 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02002924static struct bind_kw_list bind_kws = { "SSL", { }, {
Emeric Brunfb510ea2012-10-05 12:00:26 +02002925 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002926 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
2927 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02002928 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002929 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
2930 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
2931 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002932 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
2933 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
2934 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
2935 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02002936 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
2937 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
2938 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
2939 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002940 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002941 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002942 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002943 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002944 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002945 { NULL, NULL, 0 },
2946}};
Emeric Brun46591952012-05-18 15:47:34 +02002947
Willy Tarreau92faadf2012-10-10 23:04:25 +02002948/* Note: must not be declared <const> as its list will be overwritten.
2949 * Please take care of keeping this list alphabetically sorted, doing so helps
2950 * all code contributors.
2951 * Optional keywords are also declared with a NULL ->parse() function so that
2952 * the config parser can report an appropriate error when a known keyword was
2953 * not enabled.
2954 */
2955static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02002956 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002957 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
2958 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02002959 { "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 +02002960 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002961 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
2962 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
2963 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
2964 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
2965 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
2966 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
2967 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
2968 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02002969 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002970 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02002971 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Willy Tarreau92faadf2012-10-10 23:04:25 +02002972 { NULL, NULL, 0, 0 },
2973}};
2974
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002975/* transport-layer operations for SSL sockets */
2976struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02002977 .snd_buf = ssl_sock_from_buf,
2978 .rcv_buf = ssl_sock_to_buf,
2979 .rcv_pipe = NULL,
2980 .snd_pipe = NULL,
2981 .shutr = NULL,
2982 .shutw = ssl_sock_shutw,
2983 .close = ssl_sock_close,
2984 .init = ssl_sock_init,
2985};
2986
2987__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02002988static void __ssl_sock_init(void)
2989{
Emeric Brun46591952012-05-18 15:47:34 +02002990 STACK_OF(SSL_COMP)* cm;
2991
2992 SSL_library_init();
2993 cm = SSL_COMP_get_compression_methods();
2994 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02002995 sample_register_fetches(&sample_fetch_keywords);
2996 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002997 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02002998 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02002999}
3000
3001/*
3002 * Local variables:
3003 * c-indent-level: 8
3004 * c-basic-offset: 8
3005 * End:
3006 */