blob: 580ff5a0b4396d1646fb6b8f26d1fa2c878beb3c [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)
Emeric Brun6924ef82013-03-06 14:08:53 +0100628 {
Emeric Brun2b58d042012-09-20 17:10:03 +0200629 int i;
630 EC_KEY *ecdh;
631
Emeric Brun6924ef82013-03-06 14:08:53 +0100632 i = OBJ_sn2nid(bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE);
Emeric Brun2b58d042012-09-20 17:10:03 +0200633 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",
Emeric Brun6924ef82013-03-06 14:08:53 +0100635 curproxy->id, bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE,
636 bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +0200637 cfgerr++;
638 }
639 else {
640 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
641 EC_KEY_free(ecdh);
642 }
643 }
644#endif
645
Emeric Brunfc0421f2012-09-07 17:30:07 +0200646 return cfgerr;
647}
648
Emeric Brun94324a42012-10-11 14:00:19 +0200649/* prepare ssl context from servers options. Returns an error count */
650int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
651{
652 int cfgerr = 0;
653 int options =
654 SSL_OP_ALL | /* all known workarounds for bugs */
655 SSL_OP_NO_SSLv2 |
656 SSL_OP_NO_COMPRESSION;
657 int mode =
658 SSL_MODE_ENABLE_PARTIAL_WRITE |
659 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
660 SSL_MODE_RELEASE_BUFFERS;
661
Thierry Fournier383085f2013-01-24 14:15:43 +0100662 /* Make sure openssl opens /dev/urandom before the chroot */
663 if (!ssl_initialize_random()) {
664 Alert("OpenSSL random data generator initialization failed.\n");
665 cfgerr++;
666 }
667
Emeric Brun94324a42012-10-11 14:00:19 +0200668 /* Initiate SSL context for current server */
669 srv->ssl_ctx.reused_sess = NULL;
670 if (srv->use_ssl)
671 srv->xprt = &ssl_sock;
672 if (srv->check.use_ssl)
673 srv->check.xprt = &ssl_sock;
674
675 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
676 if (!srv->ssl_ctx.ctx) {
677 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
678 proxy_type_str(curproxy), curproxy->id,
679 srv->id);
680 cfgerr++;
681 return cfgerr;
682 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200683 if (srv->ssl_ctx.client_crt) {
684 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
685 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
686 proxy_type_str(curproxy), curproxy->id,
687 srv->id, srv->ssl_ctx.client_crt);
688 cfgerr++;
689 }
690 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
691 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
692 proxy_type_str(curproxy), curproxy->id,
693 srv->id, srv->ssl_ctx.client_crt);
694 cfgerr++;
695 }
696 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
697 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
698 proxy_type_str(curproxy), curproxy->id,
699 srv->id, srv->ssl_ctx.client_crt);
700 cfgerr++;
701 }
702 }
Emeric Brun94324a42012-10-11 14:00:19 +0200703
704 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
705 options |= SSL_OP_NO_SSLv3;
706 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
707 options |= SSL_OP_NO_TLSv1;
708 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
709 options |= SSL_OP_NO_TLSv1_1;
710 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
711 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200712 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
713 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200714 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
715 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
716 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
717 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
718#if SSL_OP_NO_TLSv1_1
719 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
720 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
721#endif
722#if SSL_OP_NO_TLSv1_2
723 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
724 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
725#endif
726
727 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
728 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Emeric Brunef42d922012-10-11 16:11:36 +0200729 SSL_CTX_set_verify(srv->ssl_ctx.ctx, srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE, NULL);
730 if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
731 if (srv->ssl_ctx.ca_file) {
732 /* load CAfile to verify */
733 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
734 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
735 curproxy->id, srv->id,
736 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
737 cfgerr++;
738 }
739 }
740#ifdef X509_V_FLAG_CRL_CHECK
741 if (srv->ssl_ctx.crl_file) {
742 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
743
744 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
745 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
746 curproxy->id, srv->id,
747 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
748 cfgerr++;
749 }
750 else {
751 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
752 }
753 }
754#endif
755 }
756
Emeric Brun4f65bff2012-11-16 15:11:00 +0100757 if (global.tune.ssllifetime)
758 SSL_CTX_set_timeout(srv->ssl_ctx.ctx, global.tune.ssllifetime);
759
Emeric Brun94324a42012-10-11 14:00:19 +0200760 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
761 if (srv->ssl_ctx.ciphers &&
762 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
763 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
764 curproxy->id, srv->id,
765 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
766 cfgerr++;
767 }
768
769 return cfgerr;
770}
771
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200772/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200773 * be NULL, in which case nothing is done. Returns the number of errors
774 * encountered.
775 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200776int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200777{
778 struct ebmb_node *node;
779 struct sni_ctx *sni;
780 int err = 0;
781
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200782 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200783 return 0;
784
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200785 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200786 while (node) {
787 sni = ebmb_entry(node, struct sni_ctx, name);
788 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200789 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200790 node = ebmb_next(node);
791 }
792
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200793 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200794 while (node) {
795 sni = ebmb_entry(node, struct sni_ctx, name);
796 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200797 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200798 node = ebmb_next(node);
799 }
800 return err;
801}
802
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200803/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200804 * be NULL, in which case nothing is done. The default_ctx is nullified too.
805 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200806void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200807{
808 struct ebmb_node *node, *back;
809 struct sni_ctx *sni;
810
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200811 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200812 return;
813
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200814 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200815 while (node) {
816 sni = ebmb_entry(node, struct sni_ctx, name);
817 back = ebmb_next(node);
818 ebmb_delete(node);
819 if (!sni->order) /* only free the CTX on its first occurrence */
820 SSL_CTX_free(sni->ctx);
821 free(sni);
822 node = back;
823 }
824
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200825 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200826 while (node) {
827 sni = ebmb_entry(node, struct sni_ctx, name);
828 back = ebmb_next(node);
829 ebmb_delete(node);
830 if (!sni->order) /* only free the CTX on its first occurrence */
831 SSL_CTX_free(sni->ctx);
832 free(sni);
833 node = back;
834 }
835
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200836 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +0200837}
838
Emeric Brun46591952012-05-18 15:47:34 +0200839/*
840 * This function is called if SSL * context is not yet allocated. The function
841 * is designed to be called before any other data-layer operation and sets the
842 * handshake flag on the connection. It is safe to call it multiple times.
843 * It returns 0 on success and -1 in error case.
844 */
845static int ssl_sock_init(struct connection *conn)
846{
847 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200848 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200849 return 0;
850
Willy Tarreau20879a02012-12-03 16:32:10 +0100851 if (global.maxsslconn && sslconns >= global.maxsslconn) {
852 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +0200853 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100854 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200855
Emeric Brun46591952012-05-18 15:47:34 +0200856 /* If it is in client mode initiate SSL session
857 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100858 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200859 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100860 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +0100861 if (!conn->xprt_ctx) {
862 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +0200863 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100864 }
Emeric Brun46591952012-05-18 15:47:34 +0200865
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200866 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100867 if (objt_server(conn->target)->ssl_ctx.reused_sess)
868 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +0200869
870 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200871 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200872
873 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200874 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200875
876 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200877 return 0;
878 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100879 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200880 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100881 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +0100882 if (!conn->xprt_ctx) {
883 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +0200884 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100885 }
Emeric Brun46591952012-05-18 15:47:34 +0200886
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200887 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200888
889 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200890 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200891
Emeric Brune1f38db2012-09-03 20:36:47 +0200892 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200893 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +0200894
Emeric Brun46591952012-05-18 15:47:34 +0200895 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200896 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200897
898 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200899 return 0;
900 }
901 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +0100902 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +0200903 return -1;
904}
905
906
907/* This is the callback which is used when an SSL handshake is pending. It
908 * updates the FD status if it wants some polling before being called again.
909 * It returns 0 if it fails in a fatal way or needs to poll to go further,
910 * otherwise it returns non-zero and removes itself from the connection's
911 * flags (the bit is provided in <flag> by the caller).
912 */
913int ssl_sock_handshake(struct connection *conn, unsigned int flag)
914{
915 int ret;
916
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200917 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200918 goto out_error;
919
Emeric Brun674b7432012-11-08 19:21:55 +0100920 /* If we use SSL_do_handshake to process a reneg initiated by
921 * the remote peer, it sometimes returns SSL_ERROR_SSL.
922 * Usually SSL_write and SSL_read are used and process implicitly
923 * the reneg handshake.
924 * Here we use SSL_peek as a workaround for reneg.
925 */
926 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
927 char c;
928
929 ret = SSL_peek(conn->xprt_ctx, &c, 1);
930 if (ret <= 0) {
931 /* handshake may have not been completed, let's find why */
932 ret = SSL_get_error(conn->xprt_ctx, ret);
933 if (ret == SSL_ERROR_WANT_WRITE) {
934 /* SSL handshake needs to write, L4 connection may not be ready */
935 __conn_sock_stop_recv(conn);
936 __conn_sock_poll_send(conn);
937 return 0;
938 }
939 else if (ret == SSL_ERROR_WANT_READ) {
940 /* handshake may have been completed but we have
941 * no more data to read.
942 */
943 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
944 ret = 1;
945 goto reneg_ok;
946 }
947 /* SSL handshake needs to read, L4 connection is ready */
948 if (conn->flags & CO_FL_WAIT_L4_CONN)
949 conn->flags &= ~CO_FL_WAIT_L4_CONN;
950 __conn_sock_stop_send(conn);
951 __conn_sock_poll_recv(conn);
952 return 0;
953 }
954 else if (ret == SSL_ERROR_SYSCALL) {
955 /* if errno is null, then connection was successfully established */
956 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
957 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +0100958 if (!conn->err_code) {
959 if (!((SSL *)conn->xprt_ctx)->packet_length)
960 if (!errno)
961 conn->err_code = CO_ER_SSL_EMPTY;
962 else
963 conn->err_code = CO_ER_SSL_ABORT;
964 else
965 conn->err_code = CO_ER_SSL_HANDSHAKE;
966 }
Emeric Brun674b7432012-11-08 19:21:55 +0100967 goto out_error;
968 }
969 else {
970 /* Fail on all other handshake errors */
971 /* Note: OpenSSL may leave unread bytes in the socket's
972 * buffer, causing an RST to be emitted upon close() on
973 * TCP sockets. We first try to drain possibly pending
974 * data to avoid this as much as possible.
975 */
976 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Willy Tarreau20879a02012-12-03 16:32:10 +0100977 if (!conn->err_code)
978 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +0100979 goto out_error;
980 }
981 }
982 /* read some data: consider handshake completed */
983 goto reneg_ok;
984 }
985
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200986 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200987 if (ret != 1) {
988 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200989 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +0200990
991 if (ret == SSL_ERROR_WANT_WRITE) {
992 /* SSL handshake needs to write, L4 connection may not be ready */
993 __conn_sock_stop_recv(conn);
994 __conn_sock_poll_send(conn);
995 return 0;
996 }
997 else if (ret == SSL_ERROR_WANT_READ) {
998 /* SSL handshake needs to read, L4 connection is ready */
999 if (conn->flags & CO_FL_WAIT_L4_CONN)
1000 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1001 __conn_sock_stop_send(conn);
1002 __conn_sock_poll_recv(conn);
1003 return 0;
1004 }
Willy Tarreau89230192012-09-28 20:22:13 +02001005 else if (ret == SSL_ERROR_SYSCALL) {
1006 /* if errno is null, then connection was successfully established */
1007 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1008 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001009
1010 if (!((SSL *)conn->xprt_ctx)->packet_length)
1011 if (!errno)
1012 conn->err_code = CO_ER_SSL_EMPTY;
1013 else
1014 conn->err_code = CO_ER_SSL_ABORT;
1015 else
1016 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +02001017 goto out_error;
1018 }
Emeric Brun46591952012-05-18 15:47:34 +02001019 else {
1020 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02001021 /* Note: OpenSSL may leave unread bytes in the socket's
1022 * buffer, causing an RST to be emitted upon close() on
1023 * TCP sockets. We first try to drain possibly pending
1024 * data to avoid this as much as possible.
1025 */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01001026 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Willy Tarreau20879a02012-12-03 16:32:10 +01001027 if (!conn->err_code)
1028 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001029 goto out_error;
1030 }
1031 }
1032
Emeric Brun674b7432012-11-08 19:21:55 +01001033reneg_ok:
1034
Emeric Brun46591952012-05-18 15:47:34 +02001035 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001036 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001037 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +02001038 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001039 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1040 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001041
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001042 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001043 }
1044 }
1045
1046 /* The connection is now established at both layers, it's time to leave */
1047 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1048 return 1;
1049
1050 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001051 /* Clear openssl global errors stack */
1052 ERR_clear_error();
1053
Emeric Brun9fa89732012-10-04 17:09:56 +02001054 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001055 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1056 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1057 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001058 }
1059
Emeric Brun46591952012-05-18 15:47:34 +02001060 /* Fail on all other handshake errors */
1061 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001062 if (!conn->err_code)
1063 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001064 return 0;
1065}
1066
1067/* Receive up to <count> bytes from connection <conn>'s socket and store them
1068 * into buffer <buf>. The caller must ensure that <count> is always smaller
1069 * than the buffer's size. Only one call to recv() is performed, unless the
1070 * buffer wraps, in which case a second call may be performed. The connection's
1071 * flags are updated with whatever special event is detected (error, read0,
1072 * empty). The caller is responsible for taking care of those events and
1073 * avoiding the call if inappropriate. The function does not call the
1074 * connection's polling update function, so the caller is responsible for this.
1075 */
1076static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1077{
1078 int ret, done = 0;
1079 int try = count;
1080
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001081 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001082 goto out_error;
1083
1084 if (conn->flags & CO_FL_HANDSHAKE)
1085 /* a handshake was requested */
1086 return 0;
1087
1088 /* compute the maximum block size we can read at once. */
1089 if (buffer_empty(buf)) {
1090 /* let's realign the buffer to optimize I/O */
1091 buf->p = buf->data;
1092 }
1093 else if (buf->data + buf->o < buf->p &&
1094 buf->p + buf->i < buf->data + buf->size) {
1095 /* remaining space wraps at the end, with a moving limit */
1096 if (try > buf->data + buf->size - (buf->p + buf->i))
1097 try = buf->data + buf->size - (buf->p + buf->i);
1098 }
1099
1100 /* read the largest possible block. For this, we perform only one call
1101 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1102 * in which case we accept to do it once again. A new attempt is made on
1103 * EINTR too.
1104 */
1105 while (try) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001106 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001107 if (conn->flags & CO_FL_ERROR) {
1108 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001109 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001110 }
Emeric Brun46591952012-05-18 15:47:34 +02001111 if (ret > 0) {
1112 buf->i += ret;
1113 done += ret;
1114 if (ret < try)
1115 break;
1116 count -= ret;
1117 try = count;
1118 }
1119 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001120 ret = SSL_get_error(conn->xprt_ctx, ret);
1121 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001122 /* error on protocol or underlying transport */
1123 if ((ret != SSL_ERROR_SYSCALL)
1124 || (errno && (errno != EAGAIN)))
1125 conn->flags |= CO_FL_ERROR;
1126
Emeric Brun644cde02012-12-14 11:21:13 +01001127 /* Clear openssl global errors stack */
1128 ERR_clear_error();
1129 }
Emeric Brun46591952012-05-18 15:47:34 +02001130 goto read0;
1131 }
1132 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001133 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001134 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001135 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001136 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001137 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001138 break;
1139 }
1140 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001141 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1142 /* handshake is running, and it may need to re-enable read */
1143 conn->flags |= CO_FL_SSL_WAIT_HS;
1144 __conn_sock_want_recv(conn);
1145 break;
1146 }
Emeric Brun46591952012-05-18 15:47:34 +02001147 /* we need to poll for retry a read later */
1148 __conn_data_poll_recv(conn);
1149 break;
1150 }
1151 /* otherwise it's a real error */
1152 goto out_error;
1153 }
1154 }
1155 return done;
1156
1157 read0:
1158 conn_sock_read0(conn);
1159 return done;
1160 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001161 /* Clear openssl global errors stack */
1162 ERR_clear_error();
1163
Emeric Brun46591952012-05-18 15:47:34 +02001164 conn->flags |= CO_FL_ERROR;
1165 return done;
1166}
1167
1168
1169/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1170 * <flags> may contain MSG_MORE to make the system hold on without sending
1171 * data too fast, but this flag is ignored at the moment.
1172 * Only one call to send() is performed, unless the buffer wraps, in which case
1173 * a second call may be performed. The connection's flags are updated with
1174 * whatever special event is detected (error, empty). The caller is responsible
1175 * for taking care of those events and avoiding the call if inappropriate. The
1176 * function does not call the connection's polling update function, so the caller
1177 * is responsible for this.
1178 */
1179static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1180{
1181 int ret, try, done;
1182
1183 done = 0;
1184
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001185 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001186 goto out_error;
1187
1188 if (conn->flags & CO_FL_HANDSHAKE)
1189 /* a handshake was requested */
1190 return 0;
1191
1192 /* send the largest possible block. For this we perform only one call
1193 * to send() unless the buffer wraps and we exactly fill the first hunk,
1194 * in which case we accept to do it once again.
1195 */
1196 while (buf->o) {
1197 try = buf->o;
Willy Tarreaubfd59462013-02-21 07:46:09 +01001198
1199 if (global.tune.ssl_max_record && try > global.tune.ssl_max_record)
1200 try = global.tune.ssl_max_record;
1201
Emeric Brun46591952012-05-18 15:47:34 +02001202 /* outgoing data may wrap at the end */
1203 if (buf->data + try > buf->p)
1204 try = buf->data + try - buf->p;
1205
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001206 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001207 if (conn->flags & CO_FL_ERROR) {
1208 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001209 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001210 }
Emeric Brun46591952012-05-18 15:47:34 +02001211 if (ret > 0) {
1212 buf->o -= ret;
1213 done += ret;
1214
Willy Tarreau5fb38032012-12-16 19:39:09 +01001215 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001216 /* optimize data alignment in the buffer */
1217 buf->p = buf->data;
1218
1219 /* if the system buffer is full, don't insist */
1220 if (ret < try)
1221 break;
1222 }
1223 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001224 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001225 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001226 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1227 /* handshake is running, and it may need to re-enable write */
1228 conn->flags |= CO_FL_SSL_WAIT_HS;
1229 __conn_sock_want_send(conn);
1230 break;
1231 }
Emeric Brun46591952012-05-18 15:47:34 +02001232 /* we need to poll to retry a write later */
1233 __conn_data_poll_send(conn);
1234 break;
1235 }
1236 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001237 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001238 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001239 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001240 break;
1241 }
1242 goto out_error;
1243 }
1244 }
1245 return done;
1246
1247 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001248 /* Clear openssl global errors stack */
1249 ERR_clear_error();
1250
Emeric Brun46591952012-05-18 15:47:34 +02001251 conn->flags |= CO_FL_ERROR;
1252 return done;
1253}
1254
Emeric Brun46591952012-05-18 15:47:34 +02001255static void ssl_sock_close(struct connection *conn) {
1256
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001257 if (conn->xprt_ctx) {
1258 SSL_free(conn->xprt_ctx);
1259 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001260 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001261 }
Emeric Brun46591952012-05-18 15:47:34 +02001262}
1263
1264/* This function tries to perform a clean shutdown on an SSL connection, and in
1265 * any case, flags the connection as reusable if no handshake was in progress.
1266 */
1267static void ssl_sock_shutw(struct connection *conn, int clean)
1268{
1269 if (conn->flags & CO_FL_HANDSHAKE)
1270 return;
1271 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001272 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1273 /* Clear openssl global errors stack */
1274 ERR_clear_error();
1275 }
Emeric Brun46591952012-05-18 15:47:34 +02001276
1277 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001278 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001279}
1280
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001281/* used for logging, may be changed for a sample fetch later */
1282const char *ssl_sock_get_cipher_name(struct connection *conn)
1283{
1284 if (!conn->xprt && !conn->xprt_ctx)
1285 return NULL;
1286 return SSL_get_cipher_name(conn->xprt_ctx);
1287}
1288
1289/* used for logging, may be changed for a sample fetch later */
1290const char *ssl_sock_get_proto_version(struct connection *conn)
1291{
1292 if (!conn->xprt && !conn->xprt_ctx)
1293 return NULL;
1294 return SSL_get_version(conn->xprt_ctx);
1295}
1296
Willy Tarreau8d598402012-10-22 17:58:39 +02001297/* Extract a serial from a cert, and copy it to a chunk.
1298 * Returns 1 if serial is found and copied, 0 if no serial found and
1299 * -1 if output is not large enough.
1300 */
1301static int
1302ssl_sock_get_serial(X509 *crt, struct chunk *out)
1303{
1304 ASN1_INTEGER *serial;
1305
1306 serial = X509_get_serialNumber(crt);
1307 if (!serial)
1308 return 0;
1309
1310 if (out->size < serial->length)
1311 return -1;
1312
1313 memcpy(out->str, serial->data, serial->length);
1314 out->len = serial->length;
1315 return 1;
1316}
1317
Emeric Brunce5ad802012-10-22 14:11:22 +02001318
1319/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1320 * Returns 1 if serial is found and copied, 0 if no valid time found
1321 * and -1 if output is not large enough.
1322 */
1323static int
1324ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1325{
1326 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1327 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1328
1329 if (gentm->length < 12)
1330 return 0;
1331 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1332 return 0;
1333 if (out->size < gentm->length-2)
1334 return -1;
1335
1336 memcpy(out->str, gentm->data+2, gentm->length-2);
1337 out->len = gentm->length-2;
1338 return 1;
1339 }
1340 else if (tm->type == V_ASN1_UTCTIME) {
1341 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1342
1343 if (utctm->length < 10)
1344 return 0;
1345 if (utctm->data[0] >= 0x35)
1346 return 0;
1347 if (out->size < utctm->length)
1348 return -1;
1349
1350 memcpy(out->str, utctm->data, utctm->length);
1351 out->len = utctm->length;
1352 return 1;
1353 }
1354
1355 return 0;
1356}
1357
Emeric Brun87855892012-10-17 17:39:35 +02001358/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1359 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1360 */
1361static int
1362ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1363{
1364 X509_NAME_ENTRY *ne;
1365 int i, j, n;
1366 int cur = 0;
1367 const char *s;
1368 char tmp[128];
1369
1370 out->len = 0;
1371 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1372 if (pos < 0)
1373 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1374 else
1375 j = i;
1376
1377 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1378 n = OBJ_obj2nid(ne->object);
1379 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1380 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1381 s = tmp;
1382 }
1383
1384 if (chunk_strcasecmp(entry, s) != 0)
1385 continue;
1386
1387 if (pos < 0)
1388 cur--;
1389 else
1390 cur++;
1391
1392 if (cur != pos)
1393 continue;
1394
1395 if (ne->value->length > out->size)
1396 return -1;
1397
1398 memcpy(out->str, ne->value->data, ne->value->length);
1399 out->len = ne->value->length;
1400 return 1;
1401 }
1402
1403 return 0;
1404
1405}
1406
1407/* Extract and format full DN from a X509_NAME and copy result into a chunk
1408 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1409 */
1410static int
1411ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1412{
1413 X509_NAME_ENTRY *ne;
1414 int i, n, ln;
1415 int l = 0;
1416 const char *s;
1417 char *p;
1418 char tmp[128];
1419
1420 out->len = 0;
1421 p = out->str;
1422 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1423 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1424 n = OBJ_obj2nid(ne->object);
1425 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1426 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1427 s = tmp;
1428 }
1429 ln = strlen(s);
1430
1431 l += 1 + ln + 1 + ne->value->length;
1432 if (l > out->size)
1433 return -1;
1434 out->len = l;
1435
1436 *(p++)='/';
1437 memcpy(p, s, ln);
1438 p += ln;
1439 *(p++)='=';
1440 memcpy(p, ne->value->data, ne->value->length);
1441 p += ne->value->length;
1442 }
1443
1444 if (!out->len)
1445 return 0;
1446
1447 return 1;
1448}
1449
Willy Tarreau7875d092012-09-10 08:20:03 +02001450/***** Below are some sample fetching functions for ACL/patterns *****/
1451
Emeric Brune64aef12012-09-21 13:15:06 +02001452/* boolean, returns true if client cert was present */
1453static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001454smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1455 const struct arg *args, struct sample *smp)
Emeric Brune64aef12012-09-21 13:15:06 +02001456{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001457 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001458 return 0;
1459
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001460 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001461 smp->flags |= SMP_F_MAY_CHANGE;
1462 return 0;
1463 }
1464
1465 smp->flags = 0;
1466 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001467 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001468
1469 return 1;
1470}
1471
Willy Tarreau8d598402012-10-22 17:58:39 +02001472/* bin, returns serial in a binary chunk */
1473static int
1474smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1475 const struct arg *args, struct sample *smp)
1476{
1477 X509 *crt = NULL;
1478 int ret = 0;
1479 struct chunk *smp_trash;
1480
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001481 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001482 return 0;
1483
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001484 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001485 smp->flags |= SMP_F_MAY_CHANGE;
1486 return 0;
1487 }
1488
1489 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001490 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001491 if (!crt)
1492 goto out;
1493
Willy Tarreau47ca5452012-12-23 20:22:19 +01001494 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001495 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1496 goto out;
1497
1498 smp->data.str = *smp_trash;
1499 smp->type = SMP_T_BIN;
1500 ret = 1;
1501out:
1502 if (crt)
1503 X509_free(crt);
1504 return ret;
1505}
Emeric Brune64aef12012-09-21 13:15:06 +02001506
Emeric Brunce5ad802012-10-22 14:11:22 +02001507/*str, returns notafter date in ASN1_UTCTIME format */
1508static int
1509smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1510 const struct arg *args, struct sample *smp)
1511{
1512 X509 *crt = NULL;
1513 int ret = 0;
1514 struct chunk *smp_trash;
1515
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001516 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001517 return 0;
1518
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001519 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001520 smp->flags |= SMP_F_MAY_CHANGE;
1521 return 0;
1522 }
1523
1524 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001525 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001526 if (!crt)
1527 goto out;
1528
Willy Tarreau47ca5452012-12-23 20:22:19 +01001529 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001530 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1531 goto out;
1532
1533 smp->data.str = *smp_trash;
1534 smp->type = SMP_T_STR;
1535 ret = 1;
1536out:
1537 if (crt)
1538 X509_free(crt);
1539 return ret;
1540}
1541
Emeric Brun87855892012-10-17 17:39:35 +02001542/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1543static int
1544smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1545 const struct arg *args, struct sample *smp)
1546{
1547 X509 *crt = NULL;
1548 X509_NAME *name;
1549 int ret = 0;
1550 struct chunk *smp_trash;
1551
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001552 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001553 return 0;
1554
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001555 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001556 smp->flags |= SMP_F_MAY_CHANGE;
1557 return 0;
1558 }
1559
1560 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001561 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001562 if (!crt)
1563 goto out;
1564
1565 name = X509_get_issuer_name(crt);
1566 if (!name)
1567 goto out;
1568
Willy Tarreau47ca5452012-12-23 20:22:19 +01001569 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001570 if (args && args[0].type == ARGT_STR) {
1571 int pos = 1;
1572
1573 if (args[1].type == ARGT_SINT)
1574 pos = args[1].data.sint;
1575 else if (args[1].type == ARGT_UINT)
1576 pos =(int)args[1].data.uint;
1577
1578 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1579 goto out;
1580 }
1581 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1582 goto out;
1583
1584 smp->type = SMP_T_STR;
1585 smp->data.str = *smp_trash;
1586 ret = 1;
1587out:
1588 if (crt)
1589 X509_free(crt);
1590 return ret;
1591}
1592
Emeric Brunce5ad802012-10-22 14:11:22 +02001593/*str, returns notbefore date in ASN1_UTCTIME format */
1594static int
1595smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1596 const struct arg *args, struct sample *smp)
1597{
1598 X509 *crt = NULL;
1599 int ret = 0;
1600 struct chunk *smp_trash;
1601
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001602 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001603 return 0;
1604
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001605 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001606 smp->flags |= SMP_F_MAY_CHANGE;
1607 return 0;
1608 }
1609
1610 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001611 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001612 if (!crt)
1613 goto out;
1614
Willy Tarreau47ca5452012-12-23 20:22:19 +01001615 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001616 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1617 goto out;
1618
1619 smp->data.str = *smp_trash;
1620 smp->type = SMP_T_STR;
1621 ret = 1;
1622out:
1623 if (crt)
1624 X509_free(crt);
1625 return ret;
1626}
1627
Emeric Brun87855892012-10-17 17:39:35 +02001628/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1629static int
1630smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1631 const struct arg *args, struct sample *smp)
1632{
1633 X509 *crt = NULL;
1634 X509_NAME *name;
1635 int ret = 0;
1636 struct chunk *smp_trash;
1637
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001638 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001639 return 0;
1640
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001641 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001642 smp->flags |= SMP_F_MAY_CHANGE;
1643 return 0;
1644 }
1645
1646 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001647 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001648 if (!crt)
1649 goto out;
1650
1651 name = X509_get_subject_name(crt);
1652 if (!name)
1653 goto out;
1654
Willy Tarreau47ca5452012-12-23 20:22:19 +01001655 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001656 if (args && args[0].type == ARGT_STR) {
1657 int pos = 1;
1658
1659 if (args[1].type == ARGT_SINT)
1660 pos = args[1].data.sint;
1661 else if (args[1].type == ARGT_UINT)
1662 pos =(int)args[1].data.uint;
1663
1664 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1665 goto out;
1666 }
1667 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1668 goto out;
1669
1670 smp->type = SMP_T_STR;
1671 smp->data.str = *smp_trash;
1672 ret = 1;
1673out:
1674 if (crt)
1675 X509_free(crt);
1676 return ret;
1677}
Emeric Brun9143d372012-12-20 15:44:16 +01001678
1679/* integer, returns true if current session use a client certificate */
1680static int
1681smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1682 const struct arg *args, struct sample *smp)
1683{
1684 X509 *crt;
1685
1686 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
1687 return 0;
1688
1689 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
1690 smp->flags |= SMP_F_MAY_CHANGE;
1691 return 0;
1692 }
1693
1694 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
1695 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
1696 if (crt) {
1697 X509_free(crt);
1698 }
1699
1700 smp->type = SMP_T_BOOL;
1701 smp->data.uint = (crt != NULL);
1702 return 1;
1703}
1704
Emeric Bruna7359fd2012-10-17 15:03:11 +02001705/* integer, returns the client certificate version */
1706static int
1707smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1708 const struct arg *args, struct sample *smp)
1709{
1710 X509 *crt;
1711
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001712 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001713 return 0;
1714
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001715 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001716 smp->flags |= SMP_F_MAY_CHANGE;
1717 return 0;
1718 }
1719
1720 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001721 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001722 if (!crt)
1723 return 0;
1724
1725 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1726 X509_free(crt);
1727 smp->type = SMP_T_UINT;
1728
1729 return 1;
1730}
1731
Emeric Brun7f56e742012-10-19 18:15:40 +02001732/* str, returns the client certificate sig alg */
1733static int
1734smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1735 const struct arg *args, struct sample *smp)
1736{
1737 X509 *crt;
1738 int nid;
1739
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001740 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02001741 return 0;
1742
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001743 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02001744 smp->flags |= SMP_F_MAY_CHANGE;
1745 return 0;
1746 }
1747
1748 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001749 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02001750 if (!crt)
1751 return 0;
1752
1753 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1754
1755 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1756 if (!smp->data.str.str)
1757 return 0;
1758
1759 smp->type = SMP_T_CSTR;
1760 smp->data.str.len = strlen(smp->data.str.str);
1761 X509_free(crt);
1762
1763 return 1;
1764}
1765
Emeric Brun521a0112012-10-22 12:22:55 +02001766/* str, returns the client certificate key alg */
1767static int
1768smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1769 const struct arg *args, struct sample *smp)
1770{
1771 X509 *crt;
1772 int nid;
1773
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001774 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02001775 return 0;
1776
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001777 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02001778 smp->flags |= SMP_F_MAY_CHANGE;
1779 return 0;
1780 }
1781
1782 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001783 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02001784 if (!crt)
1785 return 0;
1786
1787 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1788
1789 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1790 if (!smp->data.str.str)
1791 return 0;
1792
1793 smp->type = SMP_T_CSTR;
1794 smp->data.str.len = strlen(smp->data.str.str);
1795 X509_free(crt);
1796
1797 return 1;
1798}
1799
Emeric Brun2525b6b2012-10-18 15:59:43 +02001800/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02001801static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001802smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau7875d092012-09-10 08:20:03 +02001803 const struct arg *args, struct sample *smp)
1804{
1805 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001806 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02001807 return 1;
1808}
1809
Emeric Brun2525b6b2012-10-18 15:59:43 +02001810/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02001811static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001812smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1813 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02001814{
1815#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1816 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001817 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock) &&
1818 l4->si[0].conn->xprt_ctx &&
1819 SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02001820 return 1;
1821#else
1822 return 0;
1823#endif
1824}
1825
Willy Tarreau8d598402012-10-22 17:58:39 +02001826/* bin, returns serial in a binary chunk */
1827static int
1828smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1829 const struct arg *args, struct sample *smp)
1830{
1831 X509 *crt = NULL;
1832 int ret = 0;
1833 struct chunk *smp_trash;
1834
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001835 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001836 return 0;
1837
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001838 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001839 smp->flags |= SMP_F_MAY_CHANGE;
1840 return 0;
1841 }
1842
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001843 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001844 if (!crt)
1845 goto out;
1846
Willy Tarreau47ca5452012-12-23 20:22:19 +01001847 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001848 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1849 goto out;
1850
1851 smp->data.str = *smp_trash;
1852 smp->type = SMP_T_BIN;
1853 ret = 1;
1854out:
1855 return ret;
1856}
Emeric Brunce5ad802012-10-22 14:11:22 +02001857/*str, returns notafter date in ASN1_UTCTIME format */
1858static int
1859smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1860 const struct arg *args, struct sample *smp)
1861{
1862 X509 *crt = NULL;
1863 int ret = 0;
1864 struct chunk *smp_trash;
1865
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001866 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001867 return 0;
1868
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001869 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001870 smp->flags |= SMP_F_MAY_CHANGE;
1871 return 0;
1872 }
1873
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001874 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001875 if (!crt)
1876 goto out;
1877
Willy Tarreau47ca5452012-12-23 20:22:19 +01001878 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001879 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1880 goto out;
1881
1882 smp->data.str = *smp_trash;
1883 smp->type = SMP_T_STR;
1884 ret = 1;
1885out:
1886 return ret;
1887}
1888
1889/*str, returns notbefore date in ASN1_UTCTIME format */
1890static int
1891smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1892 const struct arg *args, struct sample *smp)
1893{
1894 X509 *crt = NULL;
1895 int ret = 0;
1896 struct chunk *smp_trash;
1897
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001898 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001899 return 0;
1900
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001901 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001902 smp->flags |= SMP_F_MAY_CHANGE;
1903 return 0;
1904 }
1905
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001906 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001907 if (!crt)
1908 goto out;
1909
Willy Tarreau47ca5452012-12-23 20:22:19 +01001910 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001911 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1912 goto out;
1913
1914 smp->data.str = *smp_trash;
1915 smp->type = SMP_T_STR;
1916 ret = 1;
1917out:
1918 return ret;
1919}
Willy Tarreau8d598402012-10-22 17:58:39 +02001920
Emeric Bruna7359fd2012-10-17 15:03:11 +02001921/* integer, returns the frontend certificate version */
1922static int
1923smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1924 const struct arg *args, struct sample *smp)
1925{
1926 X509 *crt;
1927
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001928 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001929 return 0;
1930
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001931 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001932 smp->flags |= SMP_F_MAY_CHANGE;
1933 return 0;
1934 }
1935
1936 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001937 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001938 if (!crt)
1939 return 0;
1940
1941 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1942 smp->type = SMP_T_UINT;
1943
1944 return 1;
1945}
1946
Emeric Brun7f56e742012-10-19 18:15:40 +02001947/* str, returns the client certificate sig alg */
1948static int
1949smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1950 const struct arg *args, struct sample *smp)
1951{
1952 X509 *crt;
1953 int nid;
1954
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001955 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02001956 return 0;
1957
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001958 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02001959 smp->flags |= SMP_F_MAY_CHANGE;
1960 return 0;
1961 }
1962
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001963 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02001964 if (!crt)
1965 return 0;
1966
1967 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1968
1969 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1970 if (!smp->data.str.str)
1971 return 0;
1972
1973 smp->type = SMP_T_CSTR;
1974 smp->data.str.len = strlen(smp->data.str.str);
1975
1976 return 1;
1977}
1978
Emeric Brun521a0112012-10-22 12:22:55 +02001979/* str, returns the client certificate key alg */
1980static int
1981smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1982 const struct arg *args, struct sample *smp)
1983{
1984 X509 *crt;
1985 int nid;
1986
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001987 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02001988 return 0;
1989
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001990 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02001991 smp->flags |= SMP_F_MAY_CHANGE;
1992 return 0;
1993 }
1994
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001995 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02001996 if (!crt)
1997 return 0;
1998
1999 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2000
2001 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2002 if (!smp->data.str.str)
2003 return 0;
2004
2005 smp->type = SMP_T_CSTR;
2006 smp->data.str.len = strlen(smp->data.str.str);
2007
2008 return 1;
2009}
2010
Emeric Brun87855892012-10-17 17:39:35 +02002011/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2012static int
2013smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2014 const struct arg *args, struct sample *smp)
2015{
2016 X509 *crt = NULL;
2017 X509_NAME *name;
2018 int ret = 0;
2019 struct chunk *smp_trash;
2020
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002021 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002022 return 0;
2023
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002024 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002025 smp->flags |= SMP_F_MAY_CHANGE;
2026 return 0;
2027 }
2028
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002029 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002030 if (!crt)
2031 goto out;
2032
2033 name = X509_get_issuer_name(crt);
2034 if (!name)
2035 goto out;
2036
Willy Tarreau47ca5452012-12-23 20:22:19 +01002037 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002038 if (args && args[0].type == ARGT_STR) {
2039 int pos = 1;
2040
2041 if (args[1].type == ARGT_SINT)
2042 pos = args[1].data.sint;
2043 else if (args[1].type == ARGT_UINT)
2044 pos =(int)args[1].data.uint;
2045
2046 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2047 goto out;
2048 }
2049 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2050 goto out;
2051
2052 smp->type = SMP_T_STR;
2053 smp->data.str = *smp_trash;
2054 ret = 1;
2055out:
2056 return ret;
2057}
2058
2059/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2060static int
2061smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2062 const struct arg *args, struct sample *smp)
2063{
2064 X509 *crt = NULL;
2065 X509_NAME *name;
2066 int ret = 0;
2067 struct chunk *smp_trash;
2068
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002069 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002070 return 0;
2071
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002072 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002073 smp->flags |= SMP_F_MAY_CHANGE;
2074 return 0;
2075 }
2076
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002077 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002078 if (!crt)
2079 goto out;
2080
2081 name = X509_get_subject_name(crt);
2082 if (!name)
2083 goto out;
2084
Willy Tarreau47ca5452012-12-23 20:22:19 +01002085 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002086 if (args && args[0].type == ARGT_STR) {
2087 int pos = 1;
2088
2089 if (args[1].type == ARGT_SINT)
2090 pos = args[1].data.sint;
2091 else if (args[1].type == ARGT_UINT)
2092 pos =(int)args[1].data.uint;
2093
2094 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2095 goto out;
2096 }
2097 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2098 goto out;
2099
2100 smp->type = SMP_T_STR;
2101 smp->data.str = *smp_trash;
2102 ret = 1;
2103out:
2104 return ret;
2105}
2106
Emeric Brun589fcad2012-10-16 14:13:26 +02002107static int
2108smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2109 const struct arg *args, struct sample *smp)
2110{
2111 smp->flags = 0;
2112
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002113 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002114 return 0;
2115
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002116 smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002117 if (!smp->data.str.str)
2118 return 0;
2119
2120 smp->type = SMP_T_CSTR;
2121 smp->data.str.len = strlen(smp->data.str.str);
2122
2123 return 1;
2124}
2125
2126static int
2127smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2128 const struct arg *args, struct sample *smp)
2129{
2130 smp->flags = 0;
2131
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002132 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002133 return 0;
2134
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002135 if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
Emeric Brun589fcad2012-10-16 14:13:26 +02002136 return 0;
2137
2138 smp->type = SMP_T_UINT;
2139
2140 return 1;
2141}
2142
2143static int
2144smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2145 const struct arg *args, struct sample *smp)
2146{
2147 smp->flags = 0;
2148
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002149 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002150 return 0;
2151
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002152 smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002153 if (!smp->data.uint)
2154 return 0;
2155
2156 smp->type = SMP_T_UINT;
2157
2158 return 1;
2159}
2160
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002161#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002162static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002163smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2164 const struct arg *args, struct sample *smp)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002165{
Willy Tarreaua33c6542012-10-15 13:19:06 +02002166 smp->flags = 0;
2167 smp->type = SMP_T_CSTR;
2168
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002169 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002170 return 0;
2171
2172 smp->data.str.str = NULL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002173 SSL_get0_next_proto_negotiated(l4->si[0].conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002174 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2175
2176 if (!smp->data.str.str)
2177 return 0;
2178
2179 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002180}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002181#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002182
2183static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002184smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2185 const struct arg *args, struct sample *smp)
2186{
2187 smp->flags = 0;
2188
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002189 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002190 return 0;
2191
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002192 smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002193 if (!smp->data.str.str)
2194 return 0;
2195
2196 smp->type = SMP_T_CSTR;
2197 smp->data.str.len = strlen(smp->data.str.str);
2198
2199 return 1;
2200}
2201
2202static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002203smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2204 const struct arg *args, struct sample *smp)
2205{
2206#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2207 SSL_SESSION *sess;
2208
2209 smp->flags = 0;
2210 smp->type = SMP_T_CBIN;
2211
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002212 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunfe68f682012-10-16 14:59:28 +02002213 return 0;
2214
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002215 sess = SSL_get_session(l4->si[0].conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002216 if (!sess)
2217 return 0;
2218
2219 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2220 if (!smp->data.str.str || !&smp->data.str.len)
2221 return 0;
2222
2223 return 1;
2224#else
2225 return 0;
2226#endif
2227}
2228
2229static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002230smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2231 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02002232{
2233#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2234 smp->flags = 0;
2235 smp->type = SMP_T_CSTR;
2236
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002237 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau7875d092012-09-10 08:20:03 +02002238 return 0;
2239
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002240 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 +02002241 if (!smp->data.str.str)
2242 return 0;
2243
Willy Tarreau7875d092012-09-10 08:20:03 +02002244 smp->data.str.len = strlen(smp->data.str.str);
2245 return 1;
2246#else
2247 return 0;
2248#endif
2249}
2250
Emeric Brun2525b6b2012-10-18 15:59:43 +02002251/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002252static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002253smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002254 const struct arg *args, struct sample *smp)
2255{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002256 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002257 return 0;
2258
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002259 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002260 smp->flags = SMP_F_MAY_CHANGE;
2261 return 0;
2262 }
2263
2264 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002265 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002266 smp->flags = 0;
2267
2268 return 1;
2269}
2270
Emeric Brun2525b6b2012-10-18 15:59:43 +02002271/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002272static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002273smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002274 const struct arg *args, struct sample *smp)
2275{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002276 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002277 return 0;
2278
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002279 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002280 smp->flags = SMP_F_MAY_CHANGE;
2281 return 0;
2282 }
2283
2284 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002285 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002286 smp->flags = 0;
2287
2288 return 1;
2289}
2290
Emeric Brun2525b6b2012-10-18 15:59:43 +02002291/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002292static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002293smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2294 const struct arg *args, struct sample *smp)
Emeric Brunf282a812012-09-21 15:27:54 +02002295{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002296 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002297 return 0;
2298
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002299 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002300 smp->flags = SMP_F_MAY_CHANGE;
2301 return 0;
2302 }
2303
2304 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002305 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002306 smp->flags = 0;
2307
2308 return 1;
2309}
2310
Emeric Brun2525b6b2012-10-18 15:59:43 +02002311/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002312static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002313smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2314 const struct arg *args, struct sample *smp)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002315{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002316 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002317 return 0;
2318
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002319 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002320 smp->flags = SMP_F_MAY_CHANGE;
2321 return 0;
2322 }
2323
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002324 if (!l4->si[0].conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002325 return 0;
2326
2327 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002328 smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002329 smp->flags = 0;
2330
2331 return 1;
2332}
2333
Emeric Brunfb510ea2012-10-05 12:00:26 +02002334/* parse the "ca-file" bind keyword */
2335static 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 +02002336{
2337 if (!*args[cur_arg + 1]) {
2338 if (err)
2339 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2340 return ERR_ALERT | ERR_FATAL;
2341 }
2342
Emeric Brunef42d922012-10-11 16:11:36 +02002343 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2344 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2345 else
2346 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002347
Emeric Brund94b3fe2012-09-20 18:23:56 +02002348 return 0;
2349}
2350
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002351/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002352static 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 +02002353{
2354 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002355 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002356 return ERR_ALERT | ERR_FATAL;
2357 }
2358
Emeric Brun76d88952012-10-05 15:47:31 +02002359 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002360 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002361 return 0;
2362}
2363
2364/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002365static 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 +02002366{
Emeric Brunc8e8d122012-10-02 18:42:10 +02002367 char path[PATH_MAX];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002368 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002369 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002370 return ERR_ALERT | ERR_FATAL;
2371 }
2372
Emeric Brunc8e8d122012-10-02 18:42:10 +02002373 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
2374 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > PATH_MAX) {
2375 memprintf(err, "'%s' : path too long", args[cur_arg]);
2376 return ERR_ALERT | ERR_FATAL;
2377 }
2378 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2379 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2380 return ERR_ALERT | ERR_FATAL;
2381
2382 return 0;
2383 }
2384
Willy Tarreau4348fad2012-09-20 16:48:07 +02002385 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002386 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002387
2388 return 0;
2389}
2390
Emeric Brunfb510ea2012-10-05 12:00:26 +02002391/* parse the "crl-file" bind keyword */
2392static 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 +02002393{
Emeric Brun051cdab2012-10-02 19:25:50 +02002394#ifndef X509_V_FLAG_CRL_CHECK
2395 if (err)
2396 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2397 return ERR_ALERT | ERR_FATAL;
2398#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002399 if (!*args[cur_arg + 1]) {
2400 if (err)
2401 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2402 return ERR_ALERT | ERR_FATAL;
2403 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002404
Emeric Brunef42d922012-10-11 16:11:36 +02002405 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2406 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2407 else
2408 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002409
Emeric Brun2b58d042012-09-20 17:10:03 +02002410 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002411#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002412}
2413
2414/* parse the "ecdhe" bind keyword keywords */
2415static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2416{
2417#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2418 if (err)
2419 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2420 return ERR_ALERT | ERR_FATAL;
2421#elif defined(OPENSSL_NO_ECDH)
2422 if (err)
2423 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2424 return ERR_ALERT | ERR_FATAL;
2425#else
2426 if (!*args[cur_arg + 1]) {
2427 if (err)
2428 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2429 return ERR_ALERT | ERR_FATAL;
2430 }
2431
2432 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002433
2434 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002435#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002436}
2437
Emeric Brun81c00f02012-09-21 14:31:21 +02002438/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2439static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2440{
2441 int code;
2442 char *p = args[cur_arg + 1];
2443 unsigned long long *ignerr = &conf->crt_ignerr;
2444
2445 if (!*p) {
2446 if (err)
2447 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2448 return ERR_ALERT | ERR_FATAL;
2449 }
2450
2451 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2452 ignerr = &conf->ca_ignerr;
2453
2454 if (strcmp(p, "all") == 0) {
2455 *ignerr = ~0ULL;
2456 return 0;
2457 }
2458
2459 while (p) {
2460 code = atoi(p);
2461 if ((code <= 0) || (code > 63)) {
2462 if (err)
2463 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2464 args[cur_arg], code, args[cur_arg + 1]);
2465 return ERR_ALERT | ERR_FATAL;
2466 }
2467 *ignerr |= 1ULL << code;
2468 p = strchr(p, ',');
2469 if (p)
2470 p++;
2471 }
2472
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002473 return 0;
2474}
2475
2476/* parse the "force-sslv3" bind keyword */
2477static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2478{
2479 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2480 return 0;
2481}
2482
2483/* parse the "force-tlsv10" bind keyword */
2484static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2485{
2486 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002487 return 0;
2488}
2489
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002490/* parse the "force-tlsv11" bind keyword */
2491static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2492{
2493#if SSL_OP_NO_TLSv1_1
2494 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
2495 return 0;
2496#else
2497 if (err)
2498 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
2499 return ERR_ALERT | ERR_FATAL;
2500#endif
2501}
2502
2503/* parse the "force-tlsv12" bind keyword */
2504static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2505{
2506#if SSL_OP_NO_TLSv1_2
2507 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
2508 return 0;
2509#else
2510 if (err)
2511 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
2512 return ERR_ALERT | ERR_FATAL;
2513#endif
2514}
2515
2516
Emeric Brun2d0c4822012-10-02 13:45:20 +02002517/* parse the "no-tls-tickets" bind keyword */
2518static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2519{
Emeric Brun89675492012-10-05 13:48:26 +02002520 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02002521 return 0;
2522}
2523
Emeric Brun2d0c4822012-10-02 13:45:20 +02002524
Emeric Brun9b3009b2012-10-05 11:55:06 +02002525/* parse the "no-sslv3" bind keyword */
2526static 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 +02002527{
Emeric Brun89675492012-10-05 13:48:26 +02002528 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002529 return 0;
2530}
2531
Emeric Brun9b3009b2012-10-05 11:55:06 +02002532/* parse the "no-tlsv10" bind keyword */
2533static 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 +02002534{
Emeric Brun89675492012-10-05 13:48:26 +02002535 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002536 return 0;
2537}
2538
Emeric Brun9b3009b2012-10-05 11:55:06 +02002539/* parse the "no-tlsv11" bind keyword */
2540static 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 +02002541{
Emeric Brun89675492012-10-05 13:48:26 +02002542 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002543 return 0;
2544}
2545
Emeric Brun9b3009b2012-10-05 11:55:06 +02002546/* parse the "no-tlsv12" bind keyword */
2547static 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 +02002548{
Emeric Brun89675492012-10-05 13:48:26 +02002549 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002550 return 0;
2551}
2552
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002553/* parse the "npn" bind keyword */
2554static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2555{
2556#ifdef OPENSSL_NPN_NEGOTIATED
2557 char *p1, *p2;
2558
2559 if (!*args[cur_arg + 1]) {
2560 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
2561 return ERR_ALERT | ERR_FATAL;
2562 }
2563
2564 free(conf->npn_str);
2565
2566 /* the NPN string is built as a suite of (<len> <name>)* */
2567 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
2568 conf->npn_str = calloc(1, conf->npn_len);
2569 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
2570
2571 /* replace commas with the name length */
2572 p1 = conf->npn_str;
2573 p2 = p1 + 1;
2574 while (1) {
2575 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
2576 if (!p2)
2577 p2 = p1 + 1 + strlen(p1 + 1);
2578
2579 if (p2 - (p1 + 1) > 255) {
2580 *p2 = '\0';
2581 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2582 return ERR_ALERT | ERR_FATAL;
2583 }
2584
2585 *p1 = p2 - (p1 + 1);
2586 p1 = p2;
2587
2588 if (!*p2)
2589 break;
2590
2591 *(p2++) = '\0';
2592 }
2593 return 0;
2594#else
2595 if (err)
2596 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
2597 return ERR_ALERT | ERR_FATAL;
2598#endif
2599}
2600
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002601/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002602static 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 +02002603{
Willy Tarreau81796be2012-09-22 19:11:47 +02002604 struct listener *l;
2605
Willy Tarreau4348fad2012-09-20 16:48:07 +02002606 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02002607
2608 if (global.listen_default_ciphers && !conf->ciphers)
2609 conf->ciphers = strdup(global.listen_default_ciphers);
2610
Willy Tarreau81796be2012-09-22 19:11:47 +02002611 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002612 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02002613
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002614 return 0;
2615}
2616
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002617/* parse the "strict-sni" bind keyword */
2618static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2619{
2620 conf->strict_sni = 1;
2621 return 0;
2622}
2623
Emeric Brund94b3fe2012-09-20 18:23:56 +02002624/* parse the "verify" bind keyword */
2625static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2626{
2627 if (!*args[cur_arg + 1]) {
2628 if (err)
2629 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
2630 return ERR_ALERT | ERR_FATAL;
2631 }
2632
2633 if (strcmp(args[cur_arg + 1], "none") == 0)
2634 conf->verify = SSL_VERIFY_NONE;
2635 else if (strcmp(args[cur_arg + 1], "optional") == 0)
2636 conf->verify = SSL_VERIFY_PEER;
2637 else if (strcmp(args[cur_arg + 1], "required") == 0)
2638 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2639 else {
2640 if (err)
2641 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
2642 args[cur_arg], args[cur_arg + 1]);
2643 return ERR_ALERT | ERR_FATAL;
2644 }
2645
2646 return 0;
2647}
2648
Willy Tarreau92faadf2012-10-10 23:04:25 +02002649/************** "server" keywords ****************/
2650
Emeric Brunef42d922012-10-11 16:11:36 +02002651/* parse the "ca-file" server keyword */
2652static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2653{
2654 if (!*args[*cur_arg + 1]) {
2655 if (err)
2656 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
2657 return ERR_ALERT | ERR_FATAL;
2658 }
2659
2660 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2661 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2662 else
2663 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
2664
2665 return 0;
2666}
2667
Willy Tarreau92faadf2012-10-10 23:04:25 +02002668/* parse the "check-ssl" server keyword */
2669static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2670{
2671 newsrv->check.use_ssl = 1;
2672 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2673 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2674 return 0;
2675}
2676
2677/* parse the "ciphers" server keyword */
2678static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2679{
2680 if (!*args[*cur_arg + 1]) {
2681 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
2682 return ERR_ALERT | ERR_FATAL;
2683 }
2684
2685 free(newsrv->ssl_ctx.ciphers);
2686 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
2687 return 0;
2688}
2689
Emeric Brunef42d922012-10-11 16:11:36 +02002690/* parse the "crl-file" server keyword */
2691static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2692{
2693#ifndef X509_V_FLAG_CRL_CHECK
2694 if (err)
2695 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
2696 return ERR_ALERT | ERR_FATAL;
2697#else
2698 if (!*args[*cur_arg + 1]) {
2699 if (err)
2700 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
2701 return ERR_ALERT | ERR_FATAL;
2702 }
2703
2704 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2705 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2706 else
2707 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
2708
2709 return 0;
2710#endif
2711}
2712
Emeric Bruna7aa3092012-10-26 12:58:00 +02002713/* parse the "crt" server keyword */
2714static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2715{
2716 if (!*args[*cur_arg + 1]) {
2717 if (err)
2718 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
2719 return ERR_ALERT | ERR_FATAL;
2720 }
2721
2722 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
2723 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2724 else
2725 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
2726
2727 return 0;
2728}
Emeric Brunef42d922012-10-11 16:11:36 +02002729
Willy Tarreau92faadf2012-10-10 23:04:25 +02002730/* parse the "force-sslv3" server keyword */
2731static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2732{
2733 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
2734 return 0;
2735}
2736
2737/* parse the "force-tlsv10" server keyword */
2738static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2739{
2740 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
2741 return 0;
2742}
2743
2744/* parse the "force-tlsv11" server keyword */
2745static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2746{
2747#if SSL_OP_NO_TLSv1_1
2748 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
2749 return 0;
2750#else
2751 if (err)
2752 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
2753 return ERR_ALERT | ERR_FATAL;
2754#endif
2755}
2756
2757/* parse the "force-tlsv12" server keyword */
2758static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2759{
2760#if SSL_OP_NO_TLSv1_2
2761 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
2762 return 0;
2763#else
2764 if (err)
2765 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
2766 return ERR_ALERT | ERR_FATAL;
2767#endif
2768}
2769
2770/* parse the "no-sslv3" server keyword */
2771static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2772{
2773 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
2774 return 0;
2775}
2776
2777/* parse the "no-tlsv10" server keyword */
2778static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2779{
2780 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
2781 return 0;
2782}
2783
2784/* parse the "no-tlsv11" server keyword */
2785static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2786{
2787 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
2788 return 0;
2789}
2790
2791/* parse the "no-tlsv12" server keyword */
2792static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2793{
2794 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
2795 return 0;
2796}
2797
Emeric Brunf9c5c472012-10-11 15:28:34 +02002798/* parse the "no-tls-tickets" server keyword */
2799static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2800{
2801 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
2802 return 0;
2803}
2804
Willy Tarreau92faadf2012-10-10 23:04:25 +02002805/* parse the "ssl" server keyword */
2806static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2807{
2808 newsrv->use_ssl = 1;
2809 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2810 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2811 return 0;
2812}
2813
Emeric Brunef42d922012-10-11 16:11:36 +02002814/* parse the "verify" server keyword */
2815static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2816{
2817 if (!*args[*cur_arg + 1]) {
2818 if (err)
2819 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
2820 return ERR_ALERT | ERR_FATAL;
2821 }
2822
2823 if (strcmp(args[*cur_arg + 1], "none") == 0)
2824 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
2825 else if (strcmp(args[*cur_arg + 1], "required") == 0)
2826 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
2827 else {
2828 if (err)
2829 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
2830 args[*cur_arg], args[*cur_arg + 1]);
2831 return ERR_ALERT | ERR_FATAL;
2832 }
2833
2834 return 0;
2835}
2836
Willy Tarreau7875d092012-09-10 08:20:03 +02002837/* Note: must not be declared <const> as its list will be overwritten.
2838 * Please take care of keeping this list alphabetically sorted.
2839 */
2840static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
Emeric Brun2525b6b2012-10-18 15:59:43 +02002841 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2842 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2843 { "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 +02002844 { "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 +02002845 { "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 +02002846 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
2847 { "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 +02002848 { "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 +02002849 { "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 +02002850 { "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 +01002851 { "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 +02002852 { "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 +02002853 { "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 +02002854 { "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 +02002855 { "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 +02002856 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
2857 { "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 +02002858 { "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 +02002859 { "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 +02002860 { "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 +02002861 { "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 +02002862 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun589fcad2012-10-16 14:13:26 +02002863 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2864 { "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 +02002865 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
2866 { "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 +02002867#ifdef OPENSSL_NPN_NEGOTIATED
Emeric Brun2525b6b2012-10-18 15:59:43 +02002868 { "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 +02002869#endif
Emeric Brun589fcad2012-10-16 14:13:26 +02002870 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
2871 { "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 +02002872 { "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 +02002873 { "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 +02002874 { NULL, NULL, 0, 0, 0 },
2875}};
2876
2877/* Note: must not be declared <const> as its list will be overwritten.
2878 * Please take care of keeping this list alphabetically sorted.
2879 */
2880static struct acl_kw_list acl_kws = {{ },{
Emeric Brun2525b6b2012-10-18 15:59:43 +02002881 { "ssl_c_ca_err", acl_parse_int, smp_fetch_ssl_c_ca_err, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2882 { "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 },
2883 { "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 +02002884 { "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 +02002885 { "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 +02002886 { "ssl_c_notafter", acl_parse_str, smp_fetch_ssl_c_notafter, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2887 { "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 +02002888 { "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 +02002889 { "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 +02002890 { "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 +01002891 { "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 +02002892 { "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 +02002893 { "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 +02002894 { "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 +02002895 { "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 +02002896 { "ssl_f_notafter", acl_parse_str, smp_fetch_ssl_f_notafter, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2897 { "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 +02002898 { "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 +02002899 { "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 +02002900 { "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 +02002901 { "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 +02002902 { "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 +02002903 { "ssl_fc_alg_keysize", acl_parse_str, smp_fetch_ssl_fc_alg_keysize, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2904 { "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 +02002905 { "ssl_fc_has_crt", acl_parse_int, smp_fetch_ssl_fc_has_crt, acl_match_nothing, ACL_USE_L6REQ_PERMANENT, 0 },
2906 { "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 +02002907#ifdef OPENSSL_NPN_NEGOTIATED
Emeric Brun2525b6b2012-10-18 15:59:43 +02002908 { "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 +02002909#endif
Emeric Brun589fcad2012-10-16 14:13:26 +02002910 { "ssl_fc_protocol", acl_parse_str, smp_fetch_ssl_fc_protocol, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2911 { "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 +02002912 { "ssl_fc_sni", acl_parse_str, smp_fetch_ssl_fc_sni, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2913 { "ssl_fc_sni_end", acl_parse_str, smp_fetch_ssl_fc_sni, acl_match_end, ACL_USE_L6REQ_PERMANENT, 0 },
2914 { "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 +02002915 { NULL, NULL, NULL, NULL },
2916}};
2917
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002918/* Note: must not be declared <const> as its list will be overwritten.
2919 * Please take care of keeping this list alphabetically sorted, doing so helps
2920 * all code contributors.
2921 * Optional keywords are also declared with a NULL ->parse() function so that
2922 * the config parser can report an appropriate error when a known keyword was
2923 * not enabled.
2924 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02002925static struct bind_kw_list bind_kws = { "SSL", { }, {
Emeric Brunfb510ea2012-10-05 12:00:26 +02002926 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002927 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
2928 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02002929 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002930 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
2931 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
2932 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002933 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
2934 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
2935 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
2936 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02002937 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
2938 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
2939 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
2940 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002941 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002942 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002943 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002944 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002945 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002946 { NULL, NULL, 0 },
2947}};
Emeric Brun46591952012-05-18 15:47:34 +02002948
Willy Tarreau92faadf2012-10-10 23:04:25 +02002949/* Note: must not be declared <const> as its list will be overwritten.
2950 * Please take care of keeping this list alphabetically sorted, doing so helps
2951 * all code contributors.
2952 * Optional keywords are also declared with a NULL ->parse() function so that
2953 * the config parser can report an appropriate error when a known keyword was
2954 * not enabled.
2955 */
2956static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02002957 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002958 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
2959 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02002960 { "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 +02002961 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002962 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
2963 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
2964 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
2965 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
2966 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
2967 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
2968 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
2969 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02002970 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002971 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02002972 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Willy Tarreau92faadf2012-10-10 23:04:25 +02002973 { NULL, NULL, 0, 0 },
2974}};
2975
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002976/* transport-layer operations for SSL sockets */
2977struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02002978 .snd_buf = ssl_sock_from_buf,
2979 .rcv_buf = ssl_sock_to_buf,
2980 .rcv_pipe = NULL,
2981 .snd_pipe = NULL,
2982 .shutr = NULL,
2983 .shutw = ssl_sock_shutw,
2984 .close = ssl_sock_close,
2985 .init = ssl_sock_init,
2986};
2987
2988__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02002989static void __ssl_sock_init(void)
2990{
Emeric Brun46591952012-05-18 15:47:34 +02002991 STACK_OF(SSL_COMP)* cm;
2992
2993 SSL_library_init();
2994 cm = SSL_COMP_get_compression_methods();
2995 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02002996 sample_register_fetches(&sample_fetch_keywords);
2997 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002998 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02002999 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02003000}
3001
3002/*
3003 * Local variables:
3004 * c-indent-level: 8
3005 * c-basic-offset: 8
3006 * End:
3007 */