blob: 36a0481b6417200f293241049642c6628dde3cb9 [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
Willy Tarreauab861d32013-04-02 02:30:41 +0200168#ifdef OPENSSL_ALPN_NEGOTIATED
169/* This callback is used so that the server advertises the list of
170 * negociable protocols for ALPN.
171 */
172static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **data,
173 unsigned int *len, void *arg)
174{
175 struct bind_conf *conf = arg;
176
177 *data = (const unsigned char *)conf->alpn_str;
178 *len = conf->alpn_len;
179 return SSL_TLSEXT_ERR_OK;
180}
181#endif
182
Emeric Brunfc0421f2012-09-07 17:30:07 +0200183#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
184/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
185 * warning when no match is found, which implies the default (first) cert
186 * will keep being used.
187 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200188static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, struct bind_conf *s)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200189{
190 const char *servername;
191 const char *wildp = NULL;
192 struct ebmb_node *node;
193 int i;
194 (void)al; /* shut gcc stupid warning */
195
196 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100197 if (!servername) {
198 if (s->strict_sni)
199 return SSL_TLSEXT_ERR_ALERT_FATAL;
200 else
201 return SSL_TLSEXT_ERR_NOACK;
202 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200203
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100204 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200205 if (!servername[i])
206 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100207 trash.str[i] = tolower(servername[i]);
208 if (!wildp && (trash.str[i] == '.'))
209 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200210 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100211 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200212
213 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100214 node = ebst_lookup(&s->sni_ctx, trash.str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200215 if (!node) {
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100216 if (!wildp) {
217 if (s->strict_sni)
218 return SSL_TLSEXT_ERR_ALERT_FATAL;
219 else
220 return SSL_TLSEXT_ERR_ALERT_WARNING;
221 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200222 /* lookup in full wildcards names */
223 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100224 if (!node) {
225 if (s->strict_sni)
226 return SSL_TLSEXT_ERR_ALERT_FATAL;
227 else
228 return SSL_TLSEXT_ERR_ALERT_WARNING;
229 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200230 }
231
232 /* switch ctx */
233 SSL_set_SSL_CTX(ssl, container_of(node, struct sni_ctx, name)->ctx);
234 return SSL_TLSEXT_ERR_OK;
235}
236#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
237
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200238#ifndef OPENSSL_NO_DH
239/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
240 if an error occured, and 0 if parameter not found. */
241int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
242{
243 int ret = -1;
244 BIO *in;
245 DH *dh = NULL;
246
247 in = BIO_new(BIO_s_file());
248 if (in == NULL)
249 goto end;
250
251 if (BIO_read_filename(in, file) <= 0)
252 goto end;
253
254 dh = PEM_read_bio_DHparams(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
255 if (dh) {
256 SSL_CTX_set_tmp_dh(ctx, dh);
257 ret = 1;
258 goto end;
259 }
260
261 ret = 0; /* DH params not found */
Emeric Brun644cde02012-12-14 11:21:13 +0100262
263 /* Clear openssl global errors stack */
264 ERR_clear_error();
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200265end:
266 if (dh)
267 DH_free(dh);
268
269 if (in)
270 BIO_free(in);
271
272 return ret;
273}
274#endif
275
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100276int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, char *name, int len, int order)
277{
278 struct sni_ctx *sc;
279 int wild = 0;
280 int j;
281
282 if (len) {
283 if (*name == '*') {
284 wild = 1;
285 name++;
286 len--;
287 }
288 sc = malloc(sizeof(struct sni_ctx) + len + 1);
289 for (j = 0; j < len; j++)
290 sc->name.key[j] = tolower(name[j]);
291 sc->name.key[len] = 0;
292 sc->order = order++;
293 sc->ctx = ctx;
294 if (wild)
295 ebst_insert(&s->sni_w_ctx, &sc->name);
296 else
297 ebst_insert(&s->sni_ctx, &sc->name);
298 }
299 return order;
300}
301
Emeric Brunfc0421f2012-09-07 17:30:07 +0200302/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
303 * an early error happens and the caller must call SSL_CTX_free() by itelf.
304 */
Emeric Brun50bcecc2013-04-22 13:05:23 +0200305int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200306{
307 BIO *in;
308 X509 *x = NULL, *ca;
309 int i, len, err;
310 int ret = -1;
311 int order = 0;
312 X509_NAME *xname;
313 char *str;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200314#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
315 STACK_OF(GENERAL_NAME) *names;
316#endif
317
318 in = BIO_new(BIO_s_file());
319 if (in == NULL)
320 goto end;
321
322 if (BIO_read_filename(in, file) <= 0)
323 goto end;
324
325 x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
326 if (x == NULL)
327 goto end;
328
Emeric Brun50bcecc2013-04-22 13:05:23 +0200329 if (fcount) {
330 while (fcount--)
331 order = ssl_sock_add_cert_sni(ctx, s, sni_filter[fcount], strlen(sni_filter[fcount]), order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100332 }
333 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200334#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100335 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
336 if (names) {
337 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
338 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
339 if (name->type == GEN_DNS) {
340 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
341 len = strlen(str);
342 order = ssl_sock_add_cert_sni(ctx, s, str, len, order);
343 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200344 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200345 }
346 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100347 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200348 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200349#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100350 xname = X509_get_subject_name(x);
351 i = -1;
352 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
353 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
354 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
355 len = strlen(str);
356 order = ssl_sock_add_cert_sni(ctx, s, str, len, order);
357 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200358 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200359 }
360 }
361
362 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
363 if (!SSL_CTX_use_certificate(ctx, x))
364 goto end;
365
366 if (ctx->extra_certs != NULL) {
367 sk_X509_pop_free(ctx->extra_certs, X509_free);
368 ctx->extra_certs = NULL;
369 }
370
371 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata))) {
372 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
373 X509_free(ca);
374 goto end;
375 }
376 }
377
378 err = ERR_get_error();
379 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
380 /* we successfully reached the last cert in the file */
381 ret = 1;
382 }
383 ERR_clear_error();
384
385end:
386 if (x)
387 X509_free(x);
388
389 if (in)
390 BIO_free(in);
391
392 return ret;
393}
394
Emeric Brun50bcecc2013-04-22 13:05:23 +0200395static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200396{
397 int ret;
398 SSL_CTX *ctx;
399
400 ctx = SSL_CTX_new(SSLv23_server_method());
401 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200402 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
403 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200404 return 1;
405 }
406
407 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200408 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
409 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200410 SSL_CTX_free(ctx);
411 return 1;
412 }
413
Emeric Brun50bcecc2013-04-22 13:05:23 +0200414 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200415 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200416 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
417 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200418 if (ret < 0) /* serious error, must do that ourselves */
419 SSL_CTX_free(ctx);
420 return 1;
421 }
Emeric Brun61694ab2012-10-26 13:35:33 +0200422
423 if (SSL_CTX_check_private_key(ctx) <= 0) {
424 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
425 err && *err ? *err : "", path);
426 return 1;
427 }
428
Emeric Brunfc0421f2012-09-07 17:30:07 +0200429 /* we must not free the SSL_CTX anymore below, since it's already in
430 * the tree, so it will be discovered and cleaned in time.
431 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200432#ifndef OPENSSL_NO_DH
433 ret = ssl_sock_load_dh_params(ctx, path);
434 if (ret < 0) {
435 if (err)
436 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
437 *err ? *err : "", path);
438 return 1;
439 }
440#endif
441
Emeric Brunfc0421f2012-09-07 17:30:07 +0200442#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200443 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200444 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
445 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +0200446 return 1;
447 }
448#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200449 if (!bind_conf->default_ctx)
450 bind_conf->default_ctx = ctx;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200451
452 return 0;
453}
454
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200455int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200456{
457 struct dirent *de;
458 DIR *dir;
459 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +0100460 char *end;
461 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200462 int cfgerr = 0;
463
464 if (!(dir = opendir(path)))
Emeric Brun50bcecc2013-04-22 13:05:23 +0200465 return ssl_sock_load_cert_file(path, bind_conf, curproxy, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200466
467 /* strip trailing slashes, including first one */
468 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
469 *end = 0;
470
Emeric Brunfc0421f2012-09-07 17:30:07 +0200471 while ((de = readdir(dir))) {
Willy Tarreauee2663b2012-12-06 11:36:59 +0100472 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200473 if (stat(fp, &buf) != 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200474 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
475 err && *err ? *err : "", fp, strerror(errno));
Emeric Brunfc0421f2012-09-07 17:30:07 +0200476 cfgerr++;
477 continue;
478 }
479 if (!S_ISREG(buf.st_mode))
480 continue;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200481 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, curproxy, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200482 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200483 closedir(dir);
484 return cfgerr;
485}
486
Thierry Fournier383085f2013-01-24 14:15:43 +0100487/* Make sure openssl opens /dev/urandom before the chroot. The work is only
488 * done once. Zero is returned if the operation fails. No error is returned
489 * if the random is said as not implemented, because we expect that openssl
490 * will use another method once needed.
491 */
492static int ssl_initialize_random()
493{
494 unsigned char random;
495 static int random_initialized = 0;
496
497 if (!random_initialized && RAND_bytes(&random, 1) != 0)
498 random_initialized = 1;
499
500 return random_initialized;
501}
502
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100503int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
504{
505 char thisline[65536];
506 FILE *f;
507 int linenum = 0;
508 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100509
Willy Tarreauad1731d2013-04-02 17:35:58 +0200510 if ((f = fopen(file, "r")) == NULL) {
511 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100512 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200513 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100514
515 while (fgets(thisline, sizeof(thisline), f) != NULL) {
516 int arg;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200517 int newarg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100518 char *end;
519 char *args[MAX_LINE_ARGS + 1];
520 char *line = thisline;
521
522 linenum++;
523 end = line + strlen(line);
524 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
525 /* Check if we reached the limit and the last char is not \n.
526 * Watch out for the last line without the terminating '\n'!
527 */
Willy Tarreauad1731d2013-04-02 17:35:58 +0200528 memprintf(err, "line %d too long in file '%s', limit is %d characters",
529 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100530 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200531 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100532 }
533
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100534 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200535 newarg = 1;
536 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100537 if (*line == '#' || *line == '\n' || *line == '\r') {
538 /* end of string, end of loop */
539 *line = 0;
540 break;
541 }
542 else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +0200543 newarg = 1;
544 *line = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100545 }
Emeric Brun50bcecc2013-04-22 13:05:23 +0200546 else if (newarg) {
547 if (arg == MAX_LINE_ARGS) {
548 memprintf(err, "too many args on line %d in file '%s'.",
549 linenum, file);
550 cfgerr = 1;
551 break;
552 }
553 newarg = 0;
554 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100555 }
Emeric Brun50bcecc2013-04-22 13:05:23 +0200556 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100557 }
Willy Tarreauad1731d2013-04-02 17:35:58 +0200558
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100559 /* empty line */
Emeric Brun50bcecc2013-04-22 13:05:23 +0200560 if (!arg)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100561 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100562
Emeric Brun50bcecc2013-04-22 13:05:23 +0200563 cfgerr = ssl_sock_load_cert_file(args[0], bind_conf, curproxy, &args[1], arg-1, err);
Willy Tarreauad1731d2013-04-02 17:35:58 +0200564 if (cfgerr) {
565 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100566 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200567 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100568 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100569 fclose(f);
570 return cfgerr;
571}
572
Emeric Brunfc0421f2012-09-07 17:30:07 +0200573#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
574#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
575#endif
576
577#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
578#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
Willy Tarreau7d588ee2012-11-26 18:47:31 +0100579#define SSL_renegotiate_pending(arg) 0
Emeric Brunfc0421f2012-09-07 17:30:07 +0200580#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200581#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
582#define SSL_OP_SINGLE_ECDH_USE 0
583#endif
Emeric Brun2d0c4822012-10-02 13:45:20 +0200584#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
585#define SSL_OP_NO_TICKET 0
586#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200587#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
588#define SSL_OP_NO_COMPRESSION 0
589#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +0200590#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
591#define SSL_OP_NO_TLSv1_1 0
592#endif
593#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
594#define SSL_OP_NO_TLSv1_2 0
595#endif
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200596#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
597#define SSL_OP_SINGLE_DH_USE 0
598#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200599#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
600#define SSL_OP_SINGLE_ECDH_USE 0
601#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200602#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
603#define SSL_MODE_RELEASE_BUFFERS 0
604#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200605int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy *curproxy)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200606{
607 int cfgerr = 0;
608 int ssloptions =
609 SSL_OP_ALL | /* all known workarounds for bugs */
610 SSL_OP_NO_SSLv2 |
611 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200612 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +0200613 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +0200614 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
615 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200616 int sslmode =
617 SSL_MODE_ENABLE_PARTIAL_WRITE |
618 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
619 SSL_MODE_RELEASE_BUFFERS;
620
Thierry Fournier383085f2013-01-24 14:15:43 +0100621 /* Make sure openssl opens /dev/urandom before the chroot */
622 if (!ssl_initialize_random()) {
623 Alert("OpenSSL random data generator initialization failed.\n");
624 cfgerr++;
625 }
626
Emeric Brun89675492012-10-05 13:48:26 +0200627 if (bind_conf->ssl_options & BC_SSL_O_NO_SSLV3)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200628 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brun89675492012-10-05 13:48:26 +0200629 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV10)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200630 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun89675492012-10-05 13:48:26 +0200631 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV11)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200632 ssloptions |= SSL_OP_NO_TLSv1_1;
Emeric Brun89675492012-10-05 13:48:26 +0200633 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV12)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200634 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun89675492012-10-05 13:48:26 +0200635 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
Emeric Brun2d0c4822012-10-02 13:45:20 +0200636 ssloptions |= SSL_OP_NO_TICKET;
Emeric Brun2cb7ae52012-10-05 14:14:21 +0200637 if (bind_conf->ssl_options & BC_SSL_O_USE_SSLV3)
638 SSL_CTX_set_ssl_version(ctx, SSLv3_server_method());
639 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV10)
640 SSL_CTX_set_ssl_version(ctx, TLSv1_server_method());
641#if SSL_OP_NO_TLSv1_1
642 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV11)
643 SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method());
644#endif
645#if SSL_OP_NO_TLSv1_2
646 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV12)
647 SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method());
648#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200649
650 SSL_CTX_set_options(ctx, ssloptions);
651 SSL_CTX_set_mode(ctx, sslmode);
Emeric Brune64aef12012-09-21 13:15:06 +0200652 SSL_CTX_set_verify(ctx, bind_conf->verify ? bind_conf->verify : SSL_VERIFY_NONE, ssl_sock_verifycbk);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200653 if (bind_conf->verify & SSL_VERIFY_PEER) {
Emeric Brunfb510ea2012-10-05 12:00:26 +0200654 if (bind_conf->ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200655 /* load CAfile to verify */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200656 if (!SSL_CTX_load_verify_locations(ctx, bind_conf->ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200657 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200658 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200659 cfgerr++;
660 }
661 /* set CA names fo client cert request, function returns void */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200662 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(bind_conf->ca_file));
Emeric Brund94b3fe2012-09-20 18:23:56 +0200663 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200664#ifdef X509_V_FLAG_CRL_CHECK
Emeric Brunfb510ea2012-10-05 12:00:26 +0200665 if (bind_conf->crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200666 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
667
Emeric Brunfb510ea2012-10-05 12:00:26 +0200668 if (!store || !X509_STORE_load_locations(store, bind_conf->crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200669 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200670 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200671 cfgerr++;
672 }
Emeric Brun561e5742012-10-02 15:20:55 +0200673 else {
674 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
675 }
Emeric Brund94b3fe2012-09-20 18:23:56 +0200676 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200677#endif
Emeric Brun644cde02012-12-14 11:21:13 +0100678 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +0200679 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200680
Emeric Brun4f65bff2012-11-16 15:11:00 +0100681 if (global.tune.ssllifetime)
682 SSL_CTX_set_timeout(ctx, global.tune.ssllifetime);
683
Emeric Brunfc0421f2012-09-07 17:30:07 +0200684 shared_context_set_cache(ctx);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200685 if (bind_conf->ciphers &&
686 !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200687 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 +0200688 curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200689 cfgerr++;
690 }
691
692 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200693#ifdef OPENSSL_NPN_NEGOTIATED
694 if (bind_conf->npn_str)
695 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
696#endif
Willy Tarreauab861d32013-04-02 02:30:41 +0200697#ifdef OPENSSL_ALPN_NEGOTIATED
698 if (bind_conf->alpn_str)
699 SSL_CTX_set_alpn_advertised_cb(ctx, ssl_sock_advertise_alpn_protos, bind_conf);
700#endif
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200701
Emeric Brunfc0421f2012-09-07 17:30:07 +0200702#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
703 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200704 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200705#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200706#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emeric Brun6924ef82013-03-06 14:08:53 +0100707 {
Emeric Brun2b58d042012-09-20 17:10:03 +0200708 int i;
709 EC_KEY *ecdh;
710
Emeric Brun6924ef82013-03-06 14:08:53 +0100711 i = OBJ_sn2nid(bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE);
Emeric Brun2b58d042012-09-20 17:10:03 +0200712 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
713 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 +0100714 curproxy->id, bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE,
715 bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +0200716 cfgerr++;
717 }
718 else {
719 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
720 EC_KEY_free(ecdh);
721 }
722 }
723#endif
724
Emeric Brunfc0421f2012-09-07 17:30:07 +0200725 return cfgerr;
726}
727
Emeric Brun94324a42012-10-11 14:00:19 +0200728/* prepare ssl context from servers options. Returns an error count */
729int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
730{
731 int cfgerr = 0;
732 int options =
733 SSL_OP_ALL | /* all known workarounds for bugs */
734 SSL_OP_NO_SSLv2 |
735 SSL_OP_NO_COMPRESSION;
736 int mode =
737 SSL_MODE_ENABLE_PARTIAL_WRITE |
738 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
739 SSL_MODE_RELEASE_BUFFERS;
740
Thierry Fournier383085f2013-01-24 14:15:43 +0100741 /* Make sure openssl opens /dev/urandom before the chroot */
742 if (!ssl_initialize_random()) {
743 Alert("OpenSSL random data generator initialization failed.\n");
744 cfgerr++;
745 }
746
Emeric Brun94324a42012-10-11 14:00:19 +0200747 /* Initiate SSL context for current server */
748 srv->ssl_ctx.reused_sess = NULL;
749 if (srv->use_ssl)
750 srv->xprt = &ssl_sock;
751 if (srv->check.use_ssl)
752 srv->check.xprt = &ssl_sock;
753
754 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
755 if (!srv->ssl_ctx.ctx) {
756 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
757 proxy_type_str(curproxy), curproxy->id,
758 srv->id);
759 cfgerr++;
760 return cfgerr;
761 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200762 if (srv->ssl_ctx.client_crt) {
763 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
764 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
765 proxy_type_str(curproxy), curproxy->id,
766 srv->id, srv->ssl_ctx.client_crt);
767 cfgerr++;
768 }
769 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
770 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
771 proxy_type_str(curproxy), curproxy->id,
772 srv->id, srv->ssl_ctx.client_crt);
773 cfgerr++;
774 }
775 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
776 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
777 proxy_type_str(curproxy), curproxy->id,
778 srv->id, srv->ssl_ctx.client_crt);
779 cfgerr++;
780 }
781 }
Emeric Brun94324a42012-10-11 14:00:19 +0200782
783 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
784 options |= SSL_OP_NO_SSLv3;
785 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
786 options |= SSL_OP_NO_TLSv1;
787 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
788 options |= SSL_OP_NO_TLSv1_1;
789 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
790 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200791 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
792 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200793 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
794 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
795 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
796 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
797#if SSL_OP_NO_TLSv1_1
798 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
799 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
800#endif
801#if SSL_OP_NO_TLSv1_2
802 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
803 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
804#endif
805
806 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
807 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Emeric Brunef42d922012-10-11 16:11:36 +0200808 SSL_CTX_set_verify(srv->ssl_ctx.ctx, srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE, NULL);
809 if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
810 if (srv->ssl_ctx.ca_file) {
811 /* load CAfile to verify */
812 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
813 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
814 curproxy->id, srv->id,
815 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
816 cfgerr++;
817 }
818 }
819#ifdef X509_V_FLAG_CRL_CHECK
820 if (srv->ssl_ctx.crl_file) {
821 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
822
823 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
824 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
825 curproxy->id, srv->id,
826 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
827 cfgerr++;
828 }
829 else {
830 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
831 }
832 }
833#endif
834 }
835
Emeric Brun4f65bff2012-11-16 15:11:00 +0100836 if (global.tune.ssllifetime)
837 SSL_CTX_set_timeout(srv->ssl_ctx.ctx, global.tune.ssllifetime);
838
Emeric Brun94324a42012-10-11 14:00:19 +0200839 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
840 if (srv->ssl_ctx.ciphers &&
841 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
842 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
843 curproxy->id, srv->id,
844 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
845 cfgerr++;
846 }
847
848 return cfgerr;
849}
850
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200851/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200852 * be NULL, in which case nothing is done. Returns the number of errors
853 * encountered.
854 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200855int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200856{
857 struct ebmb_node *node;
858 struct sni_ctx *sni;
859 int err = 0;
860
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200861 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200862 return 0;
863
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200864 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200865 while (node) {
866 sni = ebmb_entry(node, struct sni_ctx, name);
867 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200868 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200869 node = ebmb_next(node);
870 }
871
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200872 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200873 while (node) {
874 sni = ebmb_entry(node, struct sni_ctx, name);
875 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200876 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200877 node = ebmb_next(node);
878 }
879 return err;
880}
881
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200882/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200883 * be NULL, in which case nothing is done. The default_ctx is nullified too.
884 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200885void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200886{
887 struct ebmb_node *node, *back;
888 struct sni_ctx *sni;
889
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200890 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200891 return;
892
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200893 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200894 while (node) {
895 sni = ebmb_entry(node, struct sni_ctx, name);
896 back = ebmb_next(node);
897 ebmb_delete(node);
898 if (!sni->order) /* only free the CTX on its first occurrence */
899 SSL_CTX_free(sni->ctx);
900 free(sni);
901 node = back;
902 }
903
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200904 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200905 while (node) {
906 sni = ebmb_entry(node, struct sni_ctx, name);
907 back = ebmb_next(node);
908 ebmb_delete(node);
909 if (!sni->order) /* only free the CTX on its first occurrence */
910 SSL_CTX_free(sni->ctx);
911 free(sni);
912 node = back;
913 }
914
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200915 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +0200916}
917
Emeric Brun46591952012-05-18 15:47:34 +0200918/*
919 * This function is called if SSL * context is not yet allocated. The function
920 * is designed to be called before any other data-layer operation and sets the
921 * handshake flag on the connection. It is safe to call it multiple times.
922 * It returns 0 on success and -1 in error case.
923 */
924static int ssl_sock_init(struct connection *conn)
925{
926 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200927 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200928 return 0;
929
Willy Tarreau20879a02012-12-03 16:32:10 +0100930 if (global.maxsslconn && sslconns >= global.maxsslconn) {
931 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +0200932 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100933 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200934
Emeric Brun46591952012-05-18 15:47:34 +0200935 /* If it is in client mode initiate SSL session
936 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100937 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200938 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100939 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +0100940 if (!conn->xprt_ctx) {
941 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +0200942 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100943 }
Emeric Brun46591952012-05-18 15:47:34 +0200944
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200945 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100946 if (objt_server(conn->target)->ssl_ctx.reused_sess)
947 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +0200948
949 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200950 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200951
952 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200953 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200954
955 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200956 return 0;
957 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100958 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200959 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100960 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +0100961 if (!conn->xprt_ctx) {
962 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +0200963 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100964 }
Emeric Brun46591952012-05-18 15:47:34 +0200965
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200966 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200967
968 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200969 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200970
Emeric Brune1f38db2012-09-03 20:36:47 +0200971 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200972 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +0200973
Emeric Brun46591952012-05-18 15:47:34 +0200974 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200975 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200976
977 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200978 return 0;
979 }
980 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +0100981 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +0200982 return -1;
983}
984
985
986/* This is the callback which is used when an SSL handshake is pending. It
987 * updates the FD status if it wants some polling before being called again.
988 * It returns 0 if it fails in a fatal way or needs to poll to go further,
989 * otherwise it returns non-zero and removes itself from the connection's
990 * flags (the bit is provided in <flag> by the caller).
991 */
992int ssl_sock_handshake(struct connection *conn, unsigned int flag)
993{
994 int ret;
995
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200996 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200997 goto out_error;
998
Emeric Brun674b7432012-11-08 19:21:55 +0100999 /* If we use SSL_do_handshake to process a reneg initiated by
1000 * the remote peer, it sometimes returns SSL_ERROR_SSL.
1001 * Usually SSL_write and SSL_read are used and process implicitly
1002 * the reneg handshake.
1003 * Here we use SSL_peek as a workaround for reneg.
1004 */
1005 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
1006 char c;
1007
1008 ret = SSL_peek(conn->xprt_ctx, &c, 1);
1009 if (ret <= 0) {
1010 /* handshake may have not been completed, let's find why */
1011 ret = SSL_get_error(conn->xprt_ctx, ret);
1012 if (ret == SSL_ERROR_WANT_WRITE) {
1013 /* SSL handshake needs to write, L4 connection may not be ready */
1014 __conn_sock_stop_recv(conn);
1015 __conn_sock_poll_send(conn);
1016 return 0;
1017 }
1018 else if (ret == SSL_ERROR_WANT_READ) {
1019 /* handshake may have been completed but we have
1020 * no more data to read.
1021 */
1022 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
1023 ret = 1;
1024 goto reneg_ok;
1025 }
1026 /* SSL handshake needs to read, L4 connection is ready */
1027 if (conn->flags & CO_FL_WAIT_L4_CONN)
1028 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1029 __conn_sock_stop_send(conn);
1030 __conn_sock_poll_recv(conn);
1031 return 0;
1032 }
1033 else if (ret == SSL_ERROR_SYSCALL) {
1034 /* if errno is null, then connection was successfully established */
1035 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1036 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001037 if (!conn->err_code) {
1038 if (!((SSL *)conn->xprt_ctx)->packet_length)
1039 if (!errno)
1040 conn->err_code = CO_ER_SSL_EMPTY;
1041 else
1042 conn->err_code = CO_ER_SSL_ABORT;
1043 else
1044 conn->err_code = CO_ER_SSL_HANDSHAKE;
1045 }
Emeric Brun674b7432012-11-08 19:21:55 +01001046 goto out_error;
1047 }
1048 else {
1049 /* Fail on all other handshake errors */
1050 /* Note: OpenSSL may leave unread bytes in the socket's
1051 * buffer, causing an RST to be emitted upon close() on
1052 * TCP sockets. We first try to drain possibly pending
1053 * data to avoid this as much as possible.
1054 */
1055 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Willy Tarreau20879a02012-12-03 16:32:10 +01001056 if (!conn->err_code)
1057 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01001058 goto out_error;
1059 }
1060 }
1061 /* read some data: consider handshake completed */
1062 goto reneg_ok;
1063 }
1064
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001065 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001066 if (ret != 1) {
1067 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001068 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001069
1070 if (ret == SSL_ERROR_WANT_WRITE) {
1071 /* SSL handshake needs to write, L4 connection may not be ready */
1072 __conn_sock_stop_recv(conn);
1073 __conn_sock_poll_send(conn);
1074 return 0;
1075 }
1076 else if (ret == SSL_ERROR_WANT_READ) {
1077 /* SSL handshake needs to read, L4 connection is ready */
1078 if (conn->flags & CO_FL_WAIT_L4_CONN)
1079 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1080 __conn_sock_stop_send(conn);
1081 __conn_sock_poll_recv(conn);
1082 return 0;
1083 }
Willy Tarreau89230192012-09-28 20:22:13 +02001084 else if (ret == SSL_ERROR_SYSCALL) {
1085 /* if errno is null, then connection was successfully established */
1086 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1087 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001088
1089 if (!((SSL *)conn->xprt_ctx)->packet_length)
1090 if (!errno)
1091 conn->err_code = CO_ER_SSL_EMPTY;
1092 else
1093 conn->err_code = CO_ER_SSL_ABORT;
1094 else
1095 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +02001096 goto out_error;
1097 }
Emeric Brun46591952012-05-18 15:47:34 +02001098 else {
1099 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02001100 /* Note: OpenSSL may leave unread bytes in the socket's
1101 * buffer, causing an RST to be emitted upon close() on
1102 * TCP sockets. We first try to drain possibly pending
1103 * data to avoid this as much as possible.
1104 */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01001105 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Willy Tarreau20879a02012-12-03 16:32:10 +01001106 if (!conn->err_code)
1107 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001108 goto out_error;
1109 }
1110 }
1111
Emeric Brun674b7432012-11-08 19:21:55 +01001112reneg_ok:
1113
Emeric Brun46591952012-05-18 15:47:34 +02001114 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001115 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001116 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +02001117 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001118 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1119 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001120
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001121 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001122 }
1123 }
1124
1125 /* The connection is now established at both layers, it's time to leave */
1126 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1127 return 1;
1128
1129 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001130 /* Clear openssl global errors stack */
1131 ERR_clear_error();
1132
Emeric Brun9fa89732012-10-04 17:09:56 +02001133 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001134 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1135 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1136 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001137 }
1138
Emeric Brun46591952012-05-18 15:47:34 +02001139 /* Fail on all other handshake errors */
1140 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001141 if (!conn->err_code)
1142 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001143 return 0;
1144}
1145
1146/* Receive up to <count> bytes from connection <conn>'s socket and store them
1147 * into buffer <buf>. The caller must ensure that <count> is always smaller
1148 * than the buffer's size. Only one call to recv() is performed, unless the
1149 * buffer wraps, in which case a second call may be performed. The connection's
1150 * flags are updated with whatever special event is detected (error, read0,
1151 * empty). The caller is responsible for taking care of those events and
1152 * avoiding the call if inappropriate. The function does not call the
1153 * connection's polling update function, so the caller is responsible for this.
1154 */
1155static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1156{
1157 int ret, done = 0;
1158 int try = count;
1159
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001160 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001161 goto out_error;
1162
1163 if (conn->flags & CO_FL_HANDSHAKE)
1164 /* a handshake was requested */
1165 return 0;
1166
1167 /* compute the maximum block size we can read at once. */
1168 if (buffer_empty(buf)) {
1169 /* let's realign the buffer to optimize I/O */
1170 buf->p = buf->data;
1171 }
1172 else if (buf->data + buf->o < buf->p &&
1173 buf->p + buf->i < buf->data + buf->size) {
1174 /* remaining space wraps at the end, with a moving limit */
1175 if (try > buf->data + buf->size - (buf->p + buf->i))
1176 try = buf->data + buf->size - (buf->p + buf->i);
1177 }
1178
1179 /* read the largest possible block. For this, we perform only one call
1180 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1181 * in which case we accept to do it once again. A new attempt is made on
1182 * EINTR too.
1183 */
1184 while (try) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001185 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001186 if (conn->flags & CO_FL_ERROR) {
1187 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001188 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001189 }
Emeric Brun46591952012-05-18 15:47:34 +02001190 if (ret > 0) {
1191 buf->i += ret;
1192 done += ret;
1193 if (ret < try)
1194 break;
1195 count -= ret;
1196 try = count;
1197 }
1198 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001199 ret = SSL_get_error(conn->xprt_ctx, ret);
1200 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001201 /* error on protocol or underlying transport */
1202 if ((ret != SSL_ERROR_SYSCALL)
1203 || (errno && (errno != EAGAIN)))
1204 conn->flags |= CO_FL_ERROR;
1205
Emeric Brun644cde02012-12-14 11:21:13 +01001206 /* Clear openssl global errors stack */
1207 ERR_clear_error();
1208 }
Emeric Brun46591952012-05-18 15:47:34 +02001209 goto read0;
1210 }
1211 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001212 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001213 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001214 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001215 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001216 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001217 break;
1218 }
1219 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001220 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1221 /* handshake is running, and it may need to re-enable read */
1222 conn->flags |= CO_FL_SSL_WAIT_HS;
1223 __conn_sock_want_recv(conn);
1224 break;
1225 }
Emeric Brun46591952012-05-18 15:47:34 +02001226 /* we need to poll for retry a read later */
1227 __conn_data_poll_recv(conn);
1228 break;
1229 }
1230 /* otherwise it's a real error */
1231 goto out_error;
1232 }
1233 }
1234 return done;
1235
1236 read0:
1237 conn_sock_read0(conn);
1238 return done;
1239 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001240 /* Clear openssl global errors stack */
1241 ERR_clear_error();
1242
Emeric Brun46591952012-05-18 15:47:34 +02001243 conn->flags |= CO_FL_ERROR;
1244 return done;
1245}
1246
1247
1248/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1249 * <flags> may contain MSG_MORE to make the system hold on without sending
1250 * data too fast, but this flag is ignored at the moment.
1251 * Only one call to send() is performed, unless the buffer wraps, in which case
1252 * a second call may be performed. The connection's flags are updated with
1253 * whatever special event is detected (error, empty). The caller is responsible
1254 * for taking care of those events and avoiding the call if inappropriate. The
1255 * function does not call the connection's polling update function, so the caller
1256 * is responsible for this.
1257 */
1258static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1259{
1260 int ret, try, done;
1261
1262 done = 0;
1263
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001264 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001265 goto out_error;
1266
1267 if (conn->flags & CO_FL_HANDSHAKE)
1268 /* a handshake was requested */
1269 return 0;
1270
1271 /* send the largest possible block. For this we perform only one call
1272 * to send() unless the buffer wraps and we exactly fill the first hunk,
1273 * in which case we accept to do it once again.
1274 */
1275 while (buf->o) {
1276 try = buf->o;
Willy Tarreaubfd59462013-02-21 07:46:09 +01001277
1278 if (global.tune.ssl_max_record && try > global.tune.ssl_max_record)
1279 try = global.tune.ssl_max_record;
1280
Emeric Brun46591952012-05-18 15:47:34 +02001281 /* outgoing data may wrap at the end */
1282 if (buf->data + try > buf->p)
1283 try = buf->data + try - buf->p;
1284
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001285 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001286 if (conn->flags & CO_FL_ERROR) {
1287 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001288 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001289 }
Emeric Brun46591952012-05-18 15:47:34 +02001290 if (ret > 0) {
1291 buf->o -= ret;
1292 done += ret;
1293
Willy Tarreau5fb38032012-12-16 19:39:09 +01001294 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001295 /* optimize data alignment in the buffer */
1296 buf->p = buf->data;
1297
1298 /* if the system buffer is full, don't insist */
1299 if (ret < try)
1300 break;
1301 }
1302 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001303 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001304 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001305 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1306 /* handshake is running, and it may need to re-enable write */
1307 conn->flags |= CO_FL_SSL_WAIT_HS;
1308 __conn_sock_want_send(conn);
1309 break;
1310 }
Emeric Brun46591952012-05-18 15:47:34 +02001311 /* we need to poll to retry a write later */
1312 __conn_data_poll_send(conn);
1313 break;
1314 }
1315 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001316 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001317 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001318 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001319 break;
1320 }
1321 goto out_error;
1322 }
1323 }
1324 return done;
1325
1326 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001327 /* Clear openssl global errors stack */
1328 ERR_clear_error();
1329
Emeric Brun46591952012-05-18 15:47:34 +02001330 conn->flags |= CO_FL_ERROR;
1331 return done;
1332}
1333
Emeric Brun46591952012-05-18 15:47:34 +02001334static void ssl_sock_close(struct connection *conn) {
1335
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001336 if (conn->xprt_ctx) {
1337 SSL_free(conn->xprt_ctx);
1338 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001339 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001340 }
Emeric Brun46591952012-05-18 15:47:34 +02001341}
1342
1343/* This function tries to perform a clean shutdown on an SSL connection, and in
1344 * any case, flags the connection as reusable if no handshake was in progress.
1345 */
1346static void ssl_sock_shutw(struct connection *conn, int clean)
1347{
1348 if (conn->flags & CO_FL_HANDSHAKE)
1349 return;
1350 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001351 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1352 /* Clear openssl global errors stack */
1353 ERR_clear_error();
1354 }
Emeric Brun46591952012-05-18 15:47:34 +02001355
1356 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001357 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001358}
1359
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001360/* used for logging, may be changed for a sample fetch later */
1361const char *ssl_sock_get_cipher_name(struct connection *conn)
1362{
1363 if (!conn->xprt && !conn->xprt_ctx)
1364 return NULL;
1365 return SSL_get_cipher_name(conn->xprt_ctx);
1366}
1367
1368/* used for logging, may be changed for a sample fetch later */
1369const char *ssl_sock_get_proto_version(struct connection *conn)
1370{
1371 if (!conn->xprt && !conn->xprt_ctx)
1372 return NULL;
1373 return SSL_get_version(conn->xprt_ctx);
1374}
1375
Willy Tarreau8d598402012-10-22 17:58:39 +02001376/* Extract a serial from a cert, and copy it to a chunk.
1377 * Returns 1 if serial is found and copied, 0 if no serial found and
1378 * -1 if output is not large enough.
1379 */
1380static int
1381ssl_sock_get_serial(X509 *crt, struct chunk *out)
1382{
1383 ASN1_INTEGER *serial;
1384
1385 serial = X509_get_serialNumber(crt);
1386 if (!serial)
1387 return 0;
1388
1389 if (out->size < serial->length)
1390 return -1;
1391
1392 memcpy(out->str, serial->data, serial->length);
1393 out->len = serial->length;
1394 return 1;
1395}
1396
Emeric Brunce5ad802012-10-22 14:11:22 +02001397
1398/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1399 * Returns 1 if serial is found and copied, 0 if no valid time found
1400 * and -1 if output is not large enough.
1401 */
1402static int
1403ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1404{
1405 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1406 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1407
1408 if (gentm->length < 12)
1409 return 0;
1410 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1411 return 0;
1412 if (out->size < gentm->length-2)
1413 return -1;
1414
1415 memcpy(out->str, gentm->data+2, gentm->length-2);
1416 out->len = gentm->length-2;
1417 return 1;
1418 }
1419 else if (tm->type == V_ASN1_UTCTIME) {
1420 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1421
1422 if (utctm->length < 10)
1423 return 0;
1424 if (utctm->data[0] >= 0x35)
1425 return 0;
1426 if (out->size < utctm->length)
1427 return -1;
1428
1429 memcpy(out->str, utctm->data, utctm->length);
1430 out->len = utctm->length;
1431 return 1;
1432 }
1433
1434 return 0;
1435}
1436
Emeric Brun87855892012-10-17 17:39:35 +02001437/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1438 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1439 */
1440static int
1441ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1442{
1443 X509_NAME_ENTRY *ne;
1444 int i, j, n;
1445 int cur = 0;
1446 const char *s;
1447 char tmp[128];
1448
1449 out->len = 0;
1450 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1451 if (pos < 0)
1452 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1453 else
1454 j = i;
1455
1456 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1457 n = OBJ_obj2nid(ne->object);
1458 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1459 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1460 s = tmp;
1461 }
1462
1463 if (chunk_strcasecmp(entry, s) != 0)
1464 continue;
1465
1466 if (pos < 0)
1467 cur--;
1468 else
1469 cur++;
1470
1471 if (cur != pos)
1472 continue;
1473
1474 if (ne->value->length > out->size)
1475 return -1;
1476
1477 memcpy(out->str, ne->value->data, ne->value->length);
1478 out->len = ne->value->length;
1479 return 1;
1480 }
1481
1482 return 0;
1483
1484}
1485
1486/* Extract and format full DN from a X509_NAME and copy result into a chunk
1487 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1488 */
1489static int
1490ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1491{
1492 X509_NAME_ENTRY *ne;
1493 int i, n, ln;
1494 int l = 0;
1495 const char *s;
1496 char *p;
1497 char tmp[128];
1498
1499 out->len = 0;
1500 p = out->str;
1501 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1502 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1503 n = OBJ_obj2nid(ne->object);
1504 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1505 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1506 s = tmp;
1507 }
1508 ln = strlen(s);
1509
1510 l += 1 + ln + 1 + ne->value->length;
1511 if (l > out->size)
1512 return -1;
1513 out->len = l;
1514
1515 *(p++)='/';
1516 memcpy(p, s, ln);
1517 p += ln;
1518 *(p++)='=';
1519 memcpy(p, ne->value->data, ne->value->length);
1520 p += ne->value->length;
1521 }
1522
1523 if (!out->len)
1524 return 0;
1525
1526 return 1;
1527}
1528
Willy Tarreau7875d092012-09-10 08:20:03 +02001529/***** Below are some sample fetching functions for ACL/patterns *****/
1530
Emeric Brune64aef12012-09-21 13:15:06 +02001531/* boolean, returns true if client cert was present */
1532static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001533smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1534 const struct arg *args, struct sample *smp)
Emeric Brune64aef12012-09-21 13:15:06 +02001535{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001536 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001537 return 0;
1538
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001539 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001540 smp->flags |= SMP_F_MAY_CHANGE;
1541 return 0;
1542 }
1543
1544 smp->flags = 0;
1545 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001546 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001547
1548 return 1;
1549}
1550
Willy Tarreau8d598402012-10-22 17:58:39 +02001551/* bin, returns serial in a binary chunk */
1552static int
1553smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1554 const struct arg *args, struct sample *smp)
1555{
1556 X509 *crt = NULL;
1557 int ret = 0;
1558 struct chunk *smp_trash;
1559
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001560 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001561 return 0;
1562
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001563 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001564 smp->flags |= SMP_F_MAY_CHANGE;
1565 return 0;
1566 }
1567
1568 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001569 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001570 if (!crt)
1571 goto out;
1572
Willy Tarreau47ca5452012-12-23 20:22:19 +01001573 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001574 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1575 goto out;
1576
1577 smp->data.str = *smp_trash;
1578 smp->type = SMP_T_BIN;
1579 ret = 1;
1580out:
1581 if (crt)
1582 X509_free(crt);
1583 return ret;
1584}
Emeric Brune64aef12012-09-21 13:15:06 +02001585
Emeric Brunce5ad802012-10-22 14:11:22 +02001586/*str, returns notafter date in ASN1_UTCTIME format */
1587static int
1588smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1589 const struct arg *args, struct sample *smp)
1590{
1591 X509 *crt = NULL;
1592 int ret = 0;
1593 struct chunk *smp_trash;
1594
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001595 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001596 return 0;
1597
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001598 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001599 smp->flags |= SMP_F_MAY_CHANGE;
1600 return 0;
1601 }
1602
1603 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001604 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001605 if (!crt)
1606 goto out;
1607
Willy Tarreau47ca5452012-12-23 20:22:19 +01001608 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001609 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1610 goto out;
1611
1612 smp->data.str = *smp_trash;
1613 smp->type = SMP_T_STR;
1614 ret = 1;
1615out:
1616 if (crt)
1617 X509_free(crt);
1618 return ret;
1619}
1620
Emeric Brun87855892012-10-17 17:39:35 +02001621/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1622static int
1623smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1624 const struct arg *args, struct sample *smp)
1625{
1626 X509 *crt = NULL;
1627 X509_NAME *name;
1628 int ret = 0;
1629 struct chunk *smp_trash;
1630
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001631 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001632 return 0;
1633
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001634 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001635 smp->flags |= SMP_F_MAY_CHANGE;
1636 return 0;
1637 }
1638
1639 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001640 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001641 if (!crt)
1642 goto out;
1643
1644 name = X509_get_issuer_name(crt);
1645 if (!name)
1646 goto out;
1647
Willy Tarreau47ca5452012-12-23 20:22:19 +01001648 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001649 if (args && args[0].type == ARGT_STR) {
1650 int pos = 1;
1651
1652 if (args[1].type == ARGT_SINT)
1653 pos = args[1].data.sint;
1654 else if (args[1].type == ARGT_UINT)
1655 pos =(int)args[1].data.uint;
1656
1657 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1658 goto out;
1659 }
1660 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1661 goto out;
1662
1663 smp->type = SMP_T_STR;
1664 smp->data.str = *smp_trash;
1665 ret = 1;
1666out:
1667 if (crt)
1668 X509_free(crt);
1669 return ret;
1670}
1671
Emeric Brunce5ad802012-10-22 14:11:22 +02001672/*str, returns notbefore date in ASN1_UTCTIME format */
1673static int
1674smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1675 const struct arg *args, struct sample *smp)
1676{
1677 X509 *crt = NULL;
1678 int ret = 0;
1679 struct chunk *smp_trash;
1680
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001681 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001682 return 0;
1683
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001684 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001685 smp->flags |= SMP_F_MAY_CHANGE;
1686 return 0;
1687 }
1688
1689 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001690 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001691 if (!crt)
1692 goto out;
1693
Willy Tarreau47ca5452012-12-23 20:22:19 +01001694 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001695 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1696 goto out;
1697
1698 smp->data.str = *smp_trash;
1699 smp->type = SMP_T_STR;
1700 ret = 1;
1701out:
1702 if (crt)
1703 X509_free(crt);
1704 return ret;
1705}
1706
Emeric Brun87855892012-10-17 17:39:35 +02001707/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1708static int
1709smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1710 const struct arg *args, struct sample *smp)
1711{
1712 X509 *crt = NULL;
1713 X509_NAME *name;
1714 int ret = 0;
1715 struct chunk *smp_trash;
1716
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001717 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001718 return 0;
1719
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001720 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001721 smp->flags |= SMP_F_MAY_CHANGE;
1722 return 0;
1723 }
1724
1725 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001726 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001727 if (!crt)
1728 goto out;
1729
1730 name = X509_get_subject_name(crt);
1731 if (!name)
1732 goto out;
1733
Willy Tarreau47ca5452012-12-23 20:22:19 +01001734 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001735 if (args && args[0].type == ARGT_STR) {
1736 int pos = 1;
1737
1738 if (args[1].type == ARGT_SINT)
1739 pos = args[1].data.sint;
1740 else if (args[1].type == ARGT_UINT)
1741 pos =(int)args[1].data.uint;
1742
1743 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1744 goto out;
1745 }
1746 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1747 goto out;
1748
1749 smp->type = SMP_T_STR;
1750 smp->data.str = *smp_trash;
1751 ret = 1;
1752out:
1753 if (crt)
1754 X509_free(crt);
1755 return ret;
1756}
Emeric Brun9143d372012-12-20 15:44:16 +01001757
1758/* integer, returns true if current session use a client certificate */
1759static int
1760smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1761 const struct arg *args, struct sample *smp)
1762{
1763 X509 *crt;
1764
1765 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
1766 return 0;
1767
1768 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
1769 smp->flags |= SMP_F_MAY_CHANGE;
1770 return 0;
1771 }
1772
1773 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
1774 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
1775 if (crt) {
1776 X509_free(crt);
1777 }
1778
1779 smp->type = SMP_T_BOOL;
1780 smp->data.uint = (crt != NULL);
1781 return 1;
1782}
1783
Emeric Bruna7359fd2012-10-17 15:03:11 +02001784/* integer, returns the client certificate version */
1785static int
1786smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1787 const struct arg *args, struct sample *smp)
1788{
1789 X509 *crt;
1790
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001791 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001792 return 0;
1793
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001794 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001795 smp->flags |= SMP_F_MAY_CHANGE;
1796 return 0;
1797 }
1798
1799 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001800 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001801 if (!crt)
1802 return 0;
1803
1804 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1805 X509_free(crt);
1806 smp->type = SMP_T_UINT;
1807
1808 return 1;
1809}
1810
Emeric Brun7f56e742012-10-19 18:15:40 +02001811/* str, returns the client certificate sig alg */
1812static int
1813smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1814 const struct arg *args, struct sample *smp)
1815{
1816 X509 *crt;
1817 int nid;
1818
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001819 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02001820 return 0;
1821
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001822 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02001823 smp->flags |= SMP_F_MAY_CHANGE;
1824 return 0;
1825 }
1826
1827 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001828 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02001829 if (!crt)
1830 return 0;
1831
1832 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1833
1834 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1835 if (!smp->data.str.str)
1836 return 0;
1837
1838 smp->type = SMP_T_CSTR;
1839 smp->data.str.len = strlen(smp->data.str.str);
1840 X509_free(crt);
1841
1842 return 1;
1843}
1844
Emeric Brun521a0112012-10-22 12:22:55 +02001845/* str, returns the client certificate key alg */
1846static int
1847smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1848 const struct arg *args, struct sample *smp)
1849{
1850 X509 *crt;
1851 int nid;
1852
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001853 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02001854 return 0;
1855
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001856 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02001857 smp->flags |= SMP_F_MAY_CHANGE;
1858 return 0;
1859 }
1860
1861 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001862 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02001863 if (!crt)
1864 return 0;
1865
1866 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1867
1868 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1869 if (!smp->data.str.str)
1870 return 0;
1871
1872 smp->type = SMP_T_CSTR;
1873 smp->data.str.len = strlen(smp->data.str.str);
1874 X509_free(crt);
1875
1876 return 1;
1877}
1878
Emeric Brun2525b6b2012-10-18 15:59:43 +02001879/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02001880static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001881smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau7875d092012-09-10 08:20:03 +02001882 const struct arg *args, struct sample *smp)
1883{
1884 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001885 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02001886 return 1;
1887}
1888
Emeric Brun2525b6b2012-10-18 15:59:43 +02001889/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02001890static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001891smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1892 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02001893{
1894#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1895 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001896 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock) &&
1897 l4->si[0].conn->xprt_ctx &&
1898 SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02001899 return 1;
1900#else
1901 return 0;
1902#endif
1903}
1904
Willy Tarreau8d598402012-10-22 17:58:39 +02001905/* bin, returns serial in a binary chunk */
1906static int
1907smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1908 const struct arg *args, struct sample *smp)
1909{
1910 X509 *crt = NULL;
1911 int ret = 0;
1912 struct chunk *smp_trash;
1913
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001914 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001915 return 0;
1916
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001917 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001918 smp->flags |= SMP_F_MAY_CHANGE;
1919 return 0;
1920 }
1921
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001922 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001923 if (!crt)
1924 goto out;
1925
Willy Tarreau47ca5452012-12-23 20:22:19 +01001926 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001927 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1928 goto out;
1929
1930 smp->data.str = *smp_trash;
1931 smp->type = SMP_T_BIN;
1932 ret = 1;
1933out:
1934 return ret;
1935}
Emeric Brunce5ad802012-10-22 14:11:22 +02001936/*str, returns notafter date in ASN1_UTCTIME format */
1937static int
1938smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1939 const struct arg *args, struct sample *smp)
1940{
1941 X509 *crt = NULL;
1942 int ret = 0;
1943 struct chunk *smp_trash;
1944
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001945 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001946 return 0;
1947
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001948 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001949 smp->flags |= SMP_F_MAY_CHANGE;
1950 return 0;
1951 }
1952
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001953 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001954 if (!crt)
1955 goto out;
1956
Willy Tarreau47ca5452012-12-23 20:22:19 +01001957 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001958 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1959 goto out;
1960
1961 smp->data.str = *smp_trash;
1962 smp->type = SMP_T_STR;
1963 ret = 1;
1964out:
1965 return ret;
1966}
1967
1968/*str, returns notbefore date in ASN1_UTCTIME format */
1969static int
1970smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1971 const struct arg *args, struct sample *smp)
1972{
1973 X509 *crt = NULL;
1974 int ret = 0;
1975 struct chunk *smp_trash;
1976
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001977 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001978 return 0;
1979
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001980 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001981 smp->flags |= SMP_F_MAY_CHANGE;
1982 return 0;
1983 }
1984
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001985 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001986 if (!crt)
1987 goto out;
1988
Willy Tarreau47ca5452012-12-23 20:22:19 +01001989 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001990 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1991 goto out;
1992
1993 smp->data.str = *smp_trash;
1994 smp->type = SMP_T_STR;
1995 ret = 1;
1996out:
1997 return ret;
1998}
Willy Tarreau8d598402012-10-22 17:58:39 +02001999
Emeric Bruna7359fd2012-10-17 15:03:11 +02002000/* integer, returns the frontend certificate version */
2001static int
2002smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2003 const struct arg *args, struct sample *smp)
2004{
2005 X509 *crt;
2006
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002007 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002008 return 0;
2009
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002010 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002011 smp->flags |= SMP_F_MAY_CHANGE;
2012 return 0;
2013 }
2014
2015 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002016 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002017 if (!crt)
2018 return 0;
2019
2020 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2021 smp->type = SMP_T_UINT;
2022
2023 return 1;
2024}
2025
Emeric Brun7f56e742012-10-19 18:15:40 +02002026/* str, returns the client certificate sig alg */
2027static int
2028smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2029 const struct arg *args, struct sample *smp)
2030{
2031 X509 *crt;
2032 int nid;
2033
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002034 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02002035 return 0;
2036
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002037 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002038 smp->flags |= SMP_F_MAY_CHANGE;
2039 return 0;
2040 }
2041
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002042 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002043 if (!crt)
2044 return 0;
2045
2046 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2047
2048 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2049 if (!smp->data.str.str)
2050 return 0;
2051
2052 smp->type = SMP_T_CSTR;
2053 smp->data.str.len = strlen(smp->data.str.str);
2054
2055 return 1;
2056}
2057
Emeric Brun521a0112012-10-22 12:22:55 +02002058/* str, returns the client certificate key alg */
2059static int
2060smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2061 const struct arg *args, struct sample *smp)
2062{
2063 X509 *crt;
2064 int nid;
2065
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002066 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002067 return 0;
2068
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002069 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002070 smp->flags |= SMP_F_MAY_CHANGE;
2071 return 0;
2072 }
2073
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002074 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002075 if (!crt)
2076 return 0;
2077
2078 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2079
2080 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2081 if (!smp->data.str.str)
2082 return 0;
2083
2084 smp->type = SMP_T_CSTR;
2085 smp->data.str.len = strlen(smp->data.str.str);
2086
2087 return 1;
2088}
2089
Emeric Brun87855892012-10-17 17:39:35 +02002090/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2091static int
2092smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2093 const struct arg *args, struct sample *smp)
2094{
2095 X509 *crt = NULL;
2096 X509_NAME *name;
2097 int ret = 0;
2098 struct chunk *smp_trash;
2099
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002100 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002101 return 0;
2102
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002103 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002104 smp->flags |= SMP_F_MAY_CHANGE;
2105 return 0;
2106 }
2107
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002108 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002109 if (!crt)
2110 goto out;
2111
2112 name = X509_get_issuer_name(crt);
2113 if (!name)
2114 goto out;
2115
Willy Tarreau47ca5452012-12-23 20:22:19 +01002116 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002117 if (args && args[0].type == ARGT_STR) {
2118 int pos = 1;
2119
2120 if (args[1].type == ARGT_SINT)
2121 pos = args[1].data.sint;
2122 else if (args[1].type == ARGT_UINT)
2123 pos =(int)args[1].data.uint;
2124
2125 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2126 goto out;
2127 }
2128 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2129 goto out;
2130
2131 smp->type = SMP_T_STR;
2132 smp->data.str = *smp_trash;
2133 ret = 1;
2134out:
2135 return ret;
2136}
2137
2138/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2139static int
2140smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2141 const struct arg *args, struct sample *smp)
2142{
2143 X509 *crt = NULL;
2144 X509_NAME *name;
2145 int ret = 0;
2146 struct chunk *smp_trash;
2147
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002148 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002149 return 0;
2150
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002151 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002152 smp->flags |= SMP_F_MAY_CHANGE;
2153 return 0;
2154 }
2155
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002156 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002157 if (!crt)
2158 goto out;
2159
2160 name = X509_get_subject_name(crt);
2161 if (!name)
2162 goto out;
2163
Willy Tarreau47ca5452012-12-23 20:22:19 +01002164 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002165 if (args && args[0].type == ARGT_STR) {
2166 int pos = 1;
2167
2168 if (args[1].type == ARGT_SINT)
2169 pos = args[1].data.sint;
2170 else if (args[1].type == ARGT_UINT)
2171 pos =(int)args[1].data.uint;
2172
2173 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2174 goto out;
2175 }
2176 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2177 goto out;
2178
2179 smp->type = SMP_T_STR;
2180 smp->data.str = *smp_trash;
2181 ret = 1;
2182out:
2183 return ret;
2184}
2185
Emeric Brun589fcad2012-10-16 14:13:26 +02002186static int
2187smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2188 const struct arg *args, struct sample *smp)
2189{
2190 smp->flags = 0;
2191
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002192 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002193 return 0;
2194
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002195 smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002196 if (!smp->data.str.str)
2197 return 0;
2198
2199 smp->type = SMP_T_CSTR;
2200 smp->data.str.len = strlen(smp->data.str.str);
2201
2202 return 1;
2203}
2204
2205static int
2206smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2207 const struct arg *args, struct sample *smp)
2208{
2209 smp->flags = 0;
2210
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002211 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002212 return 0;
2213
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002214 if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
Emeric Brun589fcad2012-10-16 14:13:26 +02002215 return 0;
2216
2217 smp->type = SMP_T_UINT;
2218
2219 return 1;
2220}
2221
2222static int
2223smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2224 const struct arg *args, struct sample *smp)
2225{
2226 smp->flags = 0;
2227
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002228 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002229 return 0;
2230
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002231 smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002232 if (!smp->data.uint)
2233 return 0;
2234
2235 smp->type = SMP_T_UINT;
2236
2237 return 1;
2238}
2239
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002240#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002241static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002242smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2243 const struct arg *args, struct sample *smp)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002244{
Willy Tarreaua33c6542012-10-15 13:19:06 +02002245 smp->flags = 0;
2246 smp->type = SMP_T_CSTR;
2247
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002248 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002249 return 0;
2250
2251 smp->data.str.str = NULL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002252 SSL_get0_next_proto_negotiated(l4->si[0].conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002253 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2254
2255 if (!smp->data.str.str)
2256 return 0;
2257
2258 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002259}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002260#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002261
Willy Tarreauab861d32013-04-02 02:30:41 +02002262#ifdef OPENSSL_ALPN_NEGOTIATED
2263static int
2264smp_fetch_ssl_fc_alpn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2265 const struct arg *args, struct sample *smp)
2266{
2267 smp->flags = 0;
2268 smp->type = SMP_T_CSTR;
2269
2270 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
2271 return 0;
2272
2273 smp->data.str.str = NULL;
2274 SSL_get0_alpn_negotiated(l4->si[0].conn->xprt_ctx,
2275 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2276
2277 if (!smp->data.str.str)
2278 return 0;
2279
2280 return 1;
2281}
2282#endif
2283
Willy Tarreaua33c6542012-10-15 13:19:06 +02002284static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002285smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2286 const struct arg *args, struct sample *smp)
2287{
2288 smp->flags = 0;
2289
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002290 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002291 return 0;
2292
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002293 smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002294 if (!smp->data.str.str)
2295 return 0;
2296
2297 smp->type = SMP_T_CSTR;
2298 smp->data.str.len = strlen(smp->data.str.str);
2299
2300 return 1;
2301}
2302
2303static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002304smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2305 const struct arg *args, struct sample *smp)
2306{
2307#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2308 SSL_SESSION *sess;
2309
2310 smp->flags = 0;
2311 smp->type = SMP_T_CBIN;
2312
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002313 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunfe68f682012-10-16 14:59:28 +02002314 return 0;
2315
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002316 sess = SSL_get_session(l4->si[0].conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002317 if (!sess)
2318 return 0;
2319
2320 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2321 if (!smp->data.str.str || !&smp->data.str.len)
2322 return 0;
2323
2324 return 1;
2325#else
2326 return 0;
2327#endif
2328}
2329
2330static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002331smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2332 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02002333{
2334#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2335 smp->flags = 0;
2336 smp->type = SMP_T_CSTR;
2337
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002338 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau7875d092012-09-10 08:20:03 +02002339 return 0;
2340
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002341 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 +02002342 if (!smp->data.str.str)
2343 return 0;
2344
Willy Tarreau7875d092012-09-10 08:20:03 +02002345 smp->data.str.len = strlen(smp->data.str.str);
2346 return 1;
2347#else
2348 return 0;
2349#endif
2350}
2351
Emeric Brun2525b6b2012-10-18 15:59:43 +02002352/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002353static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002354smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002355 const struct arg *args, struct sample *smp)
2356{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002357 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002358 return 0;
2359
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002360 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002361 smp->flags = SMP_F_MAY_CHANGE;
2362 return 0;
2363 }
2364
2365 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002366 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002367 smp->flags = 0;
2368
2369 return 1;
2370}
2371
Emeric Brun2525b6b2012-10-18 15:59:43 +02002372/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002373static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002374smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002375 const struct arg *args, struct sample *smp)
2376{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002377 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002378 return 0;
2379
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002380 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002381 smp->flags = SMP_F_MAY_CHANGE;
2382 return 0;
2383 }
2384
2385 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002386 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002387 smp->flags = 0;
2388
2389 return 1;
2390}
2391
Emeric Brun2525b6b2012-10-18 15:59:43 +02002392/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002393static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002394smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2395 const struct arg *args, struct sample *smp)
Emeric Brunf282a812012-09-21 15:27:54 +02002396{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002397 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002398 return 0;
2399
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002400 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002401 smp->flags = SMP_F_MAY_CHANGE;
2402 return 0;
2403 }
2404
2405 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002406 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002407 smp->flags = 0;
2408
2409 return 1;
2410}
2411
Emeric Brun2525b6b2012-10-18 15:59:43 +02002412/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002413static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002414smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2415 const struct arg *args, struct sample *smp)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002416{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002417 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002418 return 0;
2419
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002420 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002421 smp->flags = SMP_F_MAY_CHANGE;
2422 return 0;
2423 }
2424
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002425 if (!l4->si[0].conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002426 return 0;
2427
2428 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002429 smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002430 smp->flags = 0;
2431
2432 return 1;
2433}
2434
Emeric Brunfb510ea2012-10-05 12:00:26 +02002435/* parse the "ca-file" bind keyword */
2436static 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 +02002437{
2438 if (!*args[cur_arg + 1]) {
2439 if (err)
2440 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2441 return ERR_ALERT | ERR_FATAL;
2442 }
2443
Emeric Brunef42d922012-10-11 16:11:36 +02002444 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2445 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2446 else
2447 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002448
Emeric Brund94b3fe2012-09-20 18:23:56 +02002449 return 0;
2450}
2451
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002452/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002453static 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 +02002454{
2455 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002456 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002457 return ERR_ALERT | ERR_FATAL;
2458 }
2459
Emeric Brun76d88952012-10-05 15:47:31 +02002460 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002461 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002462 return 0;
2463}
2464
2465/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002466static 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 +02002467{
Emeric Brunc8e8d122012-10-02 18:42:10 +02002468 char path[PATH_MAX];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002469 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002470 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002471 return ERR_ALERT | ERR_FATAL;
2472 }
2473
Emeric Brunc8e8d122012-10-02 18:42:10 +02002474 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
2475 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > PATH_MAX) {
2476 memprintf(err, "'%s' : path too long", args[cur_arg]);
2477 return ERR_ALERT | ERR_FATAL;
2478 }
2479 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2480 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2481 return ERR_ALERT | ERR_FATAL;
2482
2483 return 0;
2484 }
2485
Willy Tarreau4348fad2012-09-20 16:48:07 +02002486 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002487 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002488
2489 return 0;
2490}
2491
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002492/* parse the "crt-list" bind keyword */
2493static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2494{
2495 if (!*args[cur_arg + 1]) {
2496 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
2497 return ERR_ALERT | ERR_FATAL;
2498 }
2499
Willy Tarreauad1731d2013-04-02 17:35:58 +02002500 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
2501 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002502 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02002503 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002504
2505 return 0;
2506}
2507
Emeric Brunfb510ea2012-10-05 12:00:26 +02002508/* parse the "crl-file" bind keyword */
2509static 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 +02002510{
Emeric Brun051cdab2012-10-02 19:25:50 +02002511#ifndef X509_V_FLAG_CRL_CHECK
2512 if (err)
2513 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2514 return ERR_ALERT | ERR_FATAL;
2515#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002516 if (!*args[cur_arg + 1]) {
2517 if (err)
2518 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2519 return ERR_ALERT | ERR_FATAL;
2520 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002521
Emeric Brunef42d922012-10-11 16:11:36 +02002522 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2523 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2524 else
2525 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002526
Emeric Brun2b58d042012-09-20 17:10:03 +02002527 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002528#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002529}
2530
2531/* parse the "ecdhe" bind keyword keywords */
2532static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2533{
2534#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2535 if (err)
2536 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2537 return ERR_ALERT | ERR_FATAL;
2538#elif defined(OPENSSL_NO_ECDH)
2539 if (err)
2540 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2541 return ERR_ALERT | ERR_FATAL;
2542#else
2543 if (!*args[cur_arg + 1]) {
2544 if (err)
2545 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2546 return ERR_ALERT | ERR_FATAL;
2547 }
2548
2549 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002550
2551 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002552#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002553}
2554
Emeric Brun81c00f02012-09-21 14:31:21 +02002555/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2556static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2557{
2558 int code;
2559 char *p = args[cur_arg + 1];
2560 unsigned long long *ignerr = &conf->crt_ignerr;
2561
2562 if (!*p) {
2563 if (err)
2564 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2565 return ERR_ALERT | ERR_FATAL;
2566 }
2567
2568 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2569 ignerr = &conf->ca_ignerr;
2570
2571 if (strcmp(p, "all") == 0) {
2572 *ignerr = ~0ULL;
2573 return 0;
2574 }
2575
2576 while (p) {
2577 code = atoi(p);
2578 if ((code <= 0) || (code > 63)) {
2579 if (err)
2580 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2581 args[cur_arg], code, args[cur_arg + 1]);
2582 return ERR_ALERT | ERR_FATAL;
2583 }
2584 *ignerr |= 1ULL << code;
2585 p = strchr(p, ',');
2586 if (p)
2587 p++;
2588 }
2589
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002590 return 0;
2591}
2592
2593/* parse the "force-sslv3" bind keyword */
2594static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2595{
2596 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2597 return 0;
2598}
2599
2600/* parse the "force-tlsv10" bind keyword */
2601static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2602{
2603 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002604 return 0;
2605}
2606
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002607/* parse the "force-tlsv11" bind keyword */
2608static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2609{
2610#if SSL_OP_NO_TLSv1_1
2611 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
2612 return 0;
2613#else
2614 if (err)
2615 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
2616 return ERR_ALERT | ERR_FATAL;
2617#endif
2618}
2619
2620/* parse the "force-tlsv12" bind keyword */
2621static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2622{
2623#if SSL_OP_NO_TLSv1_2
2624 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
2625 return 0;
2626#else
2627 if (err)
2628 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
2629 return ERR_ALERT | ERR_FATAL;
2630#endif
2631}
2632
2633
Emeric Brun2d0c4822012-10-02 13:45:20 +02002634/* parse the "no-tls-tickets" bind keyword */
2635static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2636{
Emeric Brun89675492012-10-05 13:48:26 +02002637 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02002638 return 0;
2639}
2640
Emeric Brun2d0c4822012-10-02 13:45:20 +02002641
Emeric Brun9b3009b2012-10-05 11:55:06 +02002642/* parse the "no-sslv3" bind keyword */
2643static 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 +02002644{
Emeric Brun89675492012-10-05 13:48:26 +02002645 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002646 return 0;
2647}
2648
Emeric Brun9b3009b2012-10-05 11:55:06 +02002649/* parse the "no-tlsv10" bind keyword */
2650static 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 +02002651{
Emeric Brun89675492012-10-05 13:48:26 +02002652 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002653 return 0;
2654}
2655
Emeric Brun9b3009b2012-10-05 11:55:06 +02002656/* parse the "no-tlsv11" bind keyword */
2657static 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 +02002658{
Emeric Brun89675492012-10-05 13:48:26 +02002659 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002660 return 0;
2661}
2662
Emeric Brun9b3009b2012-10-05 11:55:06 +02002663/* parse the "no-tlsv12" bind keyword */
2664static 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 +02002665{
Emeric Brun89675492012-10-05 13:48:26 +02002666 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002667 return 0;
2668}
2669
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002670/* parse the "npn" bind keyword */
2671static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2672{
2673#ifdef OPENSSL_NPN_NEGOTIATED
2674 char *p1, *p2;
2675
2676 if (!*args[cur_arg + 1]) {
2677 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
2678 return ERR_ALERT | ERR_FATAL;
2679 }
2680
2681 free(conf->npn_str);
2682
2683 /* the NPN string is built as a suite of (<len> <name>)* */
2684 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
2685 conf->npn_str = calloc(1, conf->npn_len);
2686 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
2687
2688 /* replace commas with the name length */
2689 p1 = conf->npn_str;
2690 p2 = p1 + 1;
2691 while (1) {
2692 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
2693 if (!p2)
2694 p2 = p1 + 1 + strlen(p1 + 1);
2695
2696 if (p2 - (p1 + 1) > 255) {
2697 *p2 = '\0';
2698 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2699 return ERR_ALERT | ERR_FATAL;
2700 }
2701
2702 *p1 = p2 - (p1 + 1);
2703 p1 = p2;
2704
2705 if (!*p2)
2706 break;
2707
2708 *(p2++) = '\0';
2709 }
2710 return 0;
2711#else
2712 if (err)
2713 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
2714 return ERR_ALERT | ERR_FATAL;
2715#endif
2716}
2717
Willy Tarreauab861d32013-04-02 02:30:41 +02002718/* parse the "alpn" bind keyword */
2719static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2720{
2721#ifdef OPENSSL_ALPN_NEGOTIATED
2722 char *p1, *p2;
2723
2724 if (!*args[cur_arg + 1]) {
2725 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
2726 return ERR_ALERT | ERR_FATAL;
2727 }
2728
2729 free(conf->alpn_str);
2730
2731 /* the ALPN string is built as a suite of (<len> <name>)* */
2732 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
2733 conf->alpn_str = calloc(1, conf->alpn_len);
2734 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
2735
2736 /* replace commas with the name length */
2737 p1 = conf->alpn_str;
2738 p2 = p1 + 1;
2739 while (1) {
2740 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
2741 if (!p2)
2742 p2 = p1 + 1 + strlen(p1 + 1);
2743
2744 if (p2 - (p1 + 1) > 255) {
2745 *p2 = '\0';
2746 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2747 return ERR_ALERT | ERR_FATAL;
2748 }
2749
2750 *p1 = p2 - (p1 + 1);
2751 p1 = p2;
2752
2753 if (!*p2)
2754 break;
2755
2756 *(p2++) = '\0';
2757 }
2758 return 0;
2759#else
2760 if (err)
2761 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
2762 return ERR_ALERT | ERR_FATAL;
2763#endif
2764}
2765
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002766/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002767static 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 +02002768{
Willy Tarreau81796be2012-09-22 19:11:47 +02002769 struct listener *l;
2770
Willy Tarreau4348fad2012-09-20 16:48:07 +02002771 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02002772
2773 if (global.listen_default_ciphers && !conf->ciphers)
2774 conf->ciphers = strdup(global.listen_default_ciphers);
2775
Willy Tarreau81796be2012-09-22 19:11:47 +02002776 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002777 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02002778
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002779 return 0;
2780}
2781
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002782/* parse the "strict-sni" bind keyword */
2783static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2784{
2785 conf->strict_sni = 1;
2786 return 0;
2787}
2788
Emeric Brund94b3fe2012-09-20 18:23:56 +02002789/* parse the "verify" bind keyword */
2790static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2791{
2792 if (!*args[cur_arg + 1]) {
2793 if (err)
2794 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
2795 return ERR_ALERT | ERR_FATAL;
2796 }
2797
2798 if (strcmp(args[cur_arg + 1], "none") == 0)
2799 conf->verify = SSL_VERIFY_NONE;
2800 else if (strcmp(args[cur_arg + 1], "optional") == 0)
2801 conf->verify = SSL_VERIFY_PEER;
2802 else if (strcmp(args[cur_arg + 1], "required") == 0)
2803 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2804 else {
2805 if (err)
2806 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
2807 args[cur_arg], args[cur_arg + 1]);
2808 return ERR_ALERT | ERR_FATAL;
2809 }
2810
2811 return 0;
2812}
2813
Willy Tarreau92faadf2012-10-10 23:04:25 +02002814/************** "server" keywords ****************/
2815
Emeric Brunef42d922012-10-11 16:11:36 +02002816/* parse the "ca-file" server keyword */
2817static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2818{
2819 if (!*args[*cur_arg + 1]) {
2820 if (err)
2821 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
2822 return ERR_ALERT | ERR_FATAL;
2823 }
2824
2825 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2826 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2827 else
2828 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
2829
2830 return 0;
2831}
2832
Willy Tarreau92faadf2012-10-10 23:04:25 +02002833/* parse the "check-ssl" server keyword */
2834static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2835{
2836 newsrv->check.use_ssl = 1;
2837 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2838 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2839 return 0;
2840}
2841
2842/* parse the "ciphers" server keyword */
2843static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2844{
2845 if (!*args[*cur_arg + 1]) {
2846 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
2847 return ERR_ALERT | ERR_FATAL;
2848 }
2849
2850 free(newsrv->ssl_ctx.ciphers);
2851 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
2852 return 0;
2853}
2854
Emeric Brunef42d922012-10-11 16:11:36 +02002855/* parse the "crl-file" server keyword */
2856static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2857{
2858#ifndef X509_V_FLAG_CRL_CHECK
2859 if (err)
2860 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
2861 return ERR_ALERT | ERR_FATAL;
2862#else
2863 if (!*args[*cur_arg + 1]) {
2864 if (err)
2865 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
2866 return ERR_ALERT | ERR_FATAL;
2867 }
2868
2869 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2870 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2871 else
2872 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
2873
2874 return 0;
2875#endif
2876}
2877
Emeric Bruna7aa3092012-10-26 12:58:00 +02002878/* parse the "crt" server keyword */
2879static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2880{
2881 if (!*args[*cur_arg + 1]) {
2882 if (err)
2883 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
2884 return ERR_ALERT | ERR_FATAL;
2885 }
2886
2887 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
2888 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2889 else
2890 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
2891
2892 return 0;
2893}
Emeric Brunef42d922012-10-11 16:11:36 +02002894
Willy Tarreau92faadf2012-10-10 23:04:25 +02002895/* parse the "force-sslv3" server keyword */
2896static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2897{
2898 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
2899 return 0;
2900}
2901
2902/* parse the "force-tlsv10" server keyword */
2903static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2904{
2905 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
2906 return 0;
2907}
2908
2909/* parse the "force-tlsv11" server keyword */
2910static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2911{
2912#if SSL_OP_NO_TLSv1_1
2913 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
2914 return 0;
2915#else
2916 if (err)
2917 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
2918 return ERR_ALERT | ERR_FATAL;
2919#endif
2920}
2921
2922/* parse the "force-tlsv12" server keyword */
2923static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2924{
2925#if SSL_OP_NO_TLSv1_2
2926 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
2927 return 0;
2928#else
2929 if (err)
2930 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
2931 return ERR_ALERT | ERR_FATAL;
2932#endif
2933}
2934
2935/* parse the "no-sslv3" server keyword */
2936static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2937{
2938 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
2939 return 0;
2940}
2941
2942/* parse the "no-tlsv10" server keyword */
2943static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2944{
2945 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
2946 return 0;
2947}
2948
2949/* parse the "no-tlsv11" server keyword */
2950static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2951{
2952 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
2953 return 0;
2954}
2955
2956/* parse the "no-tlsv12" server keyword */
2957static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2958{
2959 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
2960 return 0;
2961}
2962
Emeric Brunf9c5c472012-10-11 15:28:34 +02002963/* parse the "no-tls-tickets" server keyword */
2964static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2965{
2966 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
2967 return 0;
2968}
2969
Willy Tarreau92faadf2012-10-10 23:04:25 +02002970/* parse the "ssl" server keyword */
2971static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2972{
2973 newsrv->use_ssl = 1;
2974 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2975 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2976 return 0;
2977}
2978
Emeric Brunef42d922012-10-11 16:11:36 +02002979/* parse the "verify" server keyword */
2980static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2981{
2982 if (!*args[*cur_arg + 1]) {
2983 if (err)
2984 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
2985 return ERR_ALERT | ERR_FATAL;
2986 }
2987
2988 if (strcmp(args[*cur_arg + 1], "none") == 0)
2989 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
2990 else if (strcmp(args[*cur_arg + 1], "required") == 0)
2991 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
2992 else {
2993 if (err)
2994 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
2995 args[*cur_arg], args[*cur_arg + 1]);
2996 return ERR_ALERT | ERR_FATAL;
2997 }
2998
2999 return 0;
3000}
3001
Willy Tarreau7875d092012-09-10 08:20:03 +02003002/* Note: must not be declared <const> as its list will be overwritten.
3003 * Please take care of keeping this list alphabetically sorted.
3004 */
3005static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
Willy Tarreau80aca902013-01-07 15:42:20 +01003006 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3007 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3008 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3009 { "ssl_c_i_dn", smp_fetch_ssl_c_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3010 { "ssl_c_key_alg", smp_fetch_ssl_c_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3011 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3012 { "ssl_c_notbefore", smp_fetch_ssl_c_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3013 { "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3014 { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3015 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3016 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3017 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3018 { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3019 { "ssl_f_i_dn", smp_fetch_ssl_f_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3020 { "ssl_f_key_alg", smp_fetch_ssl_f_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3021 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3022 { "ssl_f_notbefore", smp_fetch_ssl_f_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3023 { "ssl_f_sig_alg", smp_fetch_ssl_f_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3024 { "ssl_f_s_dn", smp_fetch_ssl_f_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3025 { "ssl_f_serial", smp_fetch_ssl_f_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3026 { "ssl_f_version", smp_fetch_ssl_f_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3027 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3028 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3029 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3030 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3031 { "ssl_fc_has_sni", smp_fetch_ssl_fc_has_sni, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003032#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau80aca902013-01-07 15:42:20 +01003033 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003034#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003035#ifdef OPENSSL_ALPN_NEGOTIATED
3036 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3037#endif
Willy Tarreau80aca902013-01-07 15:42:20 +01003038 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3039 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3040 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_CBIN, SMP_USE_L5CLI },
3041 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreau7875d092012-09-10 08:20:03 +02003042 { NULL, NULL, 0, 0, 0 },
3043}};
3044
3045/* Note: must not be declared <const> as its list will be overwritten.
3046 * Please take care of keeping this list alphabetically sorted.
3047 */
3048static struct acl_kw_list acl_kws = {{ },{
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003049 { "ssl_c_ca_err", NULL, acl_parse_int, acl_match_int },
3050 { "ssl_c_ca_err_depth", NULL, acl_parse_int, acl_match_int },
3051 { "ssl_c_err", NULL, acl_parse_int, acl_match_int },
3052 { "ssl_c_i_dn", NULL, acl_parse_str, acl_match_str },
3053 { "ssl_c_key_alg", NULL, acl_parse_str, acl_match_str },
3054 { "ssl_c_notafter", NULL, acl_parse_str, acl_match_str },
3055 { "ssl_c_notbefore", NULL, acl_parse_str, acl_match_str },
3056 { "ssl_c_sig_alg", NULL, acl_parse_str, acl_match_str },
3057 { "ssl_c_s_dn", NULL, acl_parse_str, acl_match_str },
3058 { "ssl_c_serial", NULL, acl_parse_bin, acl_match_bin },
3059 { "ssl_c_used", NULL, acl_parse_nothing, acl_match_nothing },
3060 { "ssl_c_verify", NULL, acl_parse_int, acl_match_int },
3061 { "ssl_c_version", NULL, acl_parse_int, acl_match_int },
3062 { "ssl_f_i_dn", NULL, acl_parse_str, acl_match_str },
3063 { "ssl_f_key_alg", NULL, acl_parse_str, acl_match_str },
3064 { "ssl_f_notafter", NULL, acl_parse_str, acl_match_str },
3065 { "ssl_f_notbefore", NULL, acl_parse_str, acl_match_str },
3066 { "ssl_f_sig_alg", NULL, acl_parse_str, acl_match_str },
3067 { "ssl_f_s_dn", NULL, acl_parse_str, acl_match_str },
3068 { "ssl_f_serial", NULL, acl_parse_bin, acl_match_bin },
3069 { "ssl_f_version", NULL, acl_parse_int, acl_match_int },
3070 { "ssl_fc", NULL, acl_parse_nothing, acl_match_nothing },
3071 { "ssl_fc_alg_keysize", NULL, acl_parse_int, acl_match_int },
3072 { "ssl_fc_cipher", NULL, acl_parse_str, acl_match_str },
3073 { "ssl_fc_has_crt", NULL, acl_parse_nothing, acl_match_nothing },
3074 { "ssl_fc_has_sni", NULL, acl_parse_nothing, acl_match_nothing },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003075#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003076 { "ssl_fc_npn", NULL, acl_parse_str, acl_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003077#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003078#ifdef OPENSSL_ALPN_NEGOTIATED
3079 { "ssl_fc_alpn", NULL, acl_parse_str, acl_match_str },
3080#endif
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003081 { "ssl_fc_protocol", NULL, acl_parse_str, acl_match_str },
3082 { "ssl_fc_use_keysize", NULL, acl_parse_int, acl_match_int },
3083 { "ssl_fc_sni", "ssl_fc_sni", acl_parse_str, acl_match_str },
3084 { "ssl_fc_sni_end", "ssl_fc_sni", acl_parse_str, acl_match_end },
3085 { "ssl_fc_sni_reg", "ssl_fc_sni", acl_parse_reg, acl_match_reg },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01003086 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02003087}};
3088
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003089/* Note: must not be declared <const> as its list will be overwritten.
3090 * Please take care of keeping this list alphabetically sorted, doing so helps
3091 * all code contributors.
3092 * Optional keywords are also declared with a NULL ->parse() function so that
3093 * the config parser can report an appropriate error when a known keyword was
3094 * not enabled.
3095 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02003096static struct bind_kw_list bind_kws = { "SSL", { }, {
Willy Tarreauab861d32013-04-02 02:30:41 +02003097 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003098 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003099 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
3100 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003101 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003102 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
3103 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003104 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003105 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003106 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
3107 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
3108 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
3109 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02003110 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
3111 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
3112 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
3113 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003114 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003115 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003116 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003117 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003118 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003119 { NULL, NULL, 0 },
3120}};
Emeric Brun46591952012-05-18 15:47:34 +02003121
Willy Tarreau92faadf2012-10-10 23:04:25 +02003122/* Note: must not be declared <const> as its list will be overwritten.
3123 * Please take care of keeping this list alphabetically sorted, doing so helps
3124 * all code contributors.
3125 * Optional keywords are also declared with a NULL ->parse() function so that
3126 * the config parser can report an appropriate error when a known keyword was
3127 * not enabled.
3128 */
3129static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02003130 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003131 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
3132 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02003133 { "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 +02003134 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003135 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
3136 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
3137 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
3138 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
3139 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
3140 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
3141 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
3142 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02003143 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003144 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02003145 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Willy Tarreau92faadf2012-10-10 23:04:25 +02003146 { NULL, NULL, 0, 0 },
3147}};
3148
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003149/* transport-layer operations for SSL sockets */
3150struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02003151 .snd_buf = ssl_sock_from_buf,
3152 .rcv_buf = ssl_sock_to_buf,
3153 .rcv_pipe = NULL,
3154 .snd_pipe = NULL,
3155 .shutr = NULL,
3156 .shutw = ssl_sock_shutw,
3157 .close = ssl_sock_close,
3158 .init = ssl_sock_init,
3159};
3160
3161__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02003162static void __ssl_sock_init(void)
3163{
Emeric Brun46591952012-05-18 15:47:34 +02003164 STACK_OF(SSL_COMP)* cm;
3165
3166 SSL_library_init();
3167 cm = SSL_COMP_get_compression_methods();
3168 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02003169 sample_register_fetches(&sample_fetch_keywords);
3170 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003171 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02003172 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02003173}
3174
3175/*
3176 * Local variables:
3177 * c-indent-level: 8
3178 * c-basic-offset: 8
3179 * End:
3180 */