blob: 917ca158a1f3512fb261e9592705ad3a819e9882 [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 */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100305int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s, char *sni_filter)
Emeric Brunfc0421f2012-09-07 17:30:07 +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
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100329 if (sni_filter) {
330 while (*sni_filter) {
331 while (isspace(*sni_filter))
332 sni_filter++;
333 str = sni_filter;
334 while (!isspace(*sni_filter) && *sni_filter)
335 sni_filter++;
336 len = sni_filter - str;
337 order = ssl_sock_add_cert_sni(ctx, s, str, len, order);
338 }
339 }
340 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200341#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100342 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
343 if (names) {
344 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
345 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
346 if (name->type == GEN_DNS) {
347 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
348 len = strlen(str);
349 order = ssl_sock_add_cert_sni(ctx, s, str, len, order);
350 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200351 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200352 }
353 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100354 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200355 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200356#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100357 xname = X509_get_subject_name(x);
358 i = -1;
359 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
360 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
361 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
362 len = strlen(str);
363 order = ssl_sock_add_cert_sni(ctx, s, str, len, order);
364 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200365 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200366 }
367 }
368
369 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
370 if (!SSL_CTX_use_certificate(ctx, x))
371 goto end;
372
373 if (ctx->extra_certs != NULL) {
374 sk_X509_pop_free(ctx->extra_certs, X509_free);
375 ctx->extra_certs = NULL;
376 }
377
378 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata))) {
379 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
380 X509_free(ca);
381 goto end;
382 }
383 }
384
385 err = ERR_get_error();
386 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
387 /* we successfully reached the last cert in the file */
388 ret = 1;
389 }
390 ERR_clear_error();
391
392end:
393 if (x)
394 X509_free(x);
395
396 if (in)
397 BIO_free(in);
398
399 return ret;
400}
401
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100402static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char *sni_filter, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200403{
404 int ret;
405 SSL_CTX *ctx;
406
407 ctx = SSL_CTX_new(SSLv23_server_method());
408 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200409 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
410 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200411 return 1;
412 }
413
414 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200415 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
416 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200417 SSL_CTX_free(ctx);
418 return 1;
419 }
420
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100421 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, sni_filter);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200422 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200423 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
424 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200425 if (ret < 0) /* serious error, must do that ourselves */
426 SSL_CTX_free(ctx);
427 return 1;
428 }
Emeric Brun61694ab2012-10-26 13:35:33 +0200429
430 if (SSL_CTX_check_private_key(ctx) <= 0) {
431 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
432 err && *err ? *err : "", path);
433 return 1;
434 }
435
Emeric Brunfc0421f2012-09-07 17:30:07 +0200436 /* we must not free the SSL_CTX anymore below, since it's already in
437 * the tree, so it will be discovered and cleaned in time.
438 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200439#ifndef OPENSSL_NO_DH
440 ret = ssl_sock_load_dh_params(ctx, path);
441 if (ret < 0) {
442 if (err)
443 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
444 *err ? *err : "", path);
445 return 1;
446 }
447#endif
448
Emeric Brunfc0421f2012-09-07 17:30:07 +0200449#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200450 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200451 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
452 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +0200453 return 1;
454 }
455#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200456 if (!bind_conf->default_ctx)
457 bind_conf->default_ctx = ctx;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200458
459 return 0;
460}
461
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200462int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200463{
464 struct dirent *de;
465 DIR *dir;
466 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +0100467 char *end;
468 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200469 int cfgerr = 0;
470
471 if (!(dir = opendir(path)))
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100472 return ssl_sock_load_cert_file(path, bind_conf, curproxy, NULL, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200473
474 /* strip trailing slashes, including first one */
475 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
476 *end = 0;
477
Emeric Brunfc0421f2012-09-07 17:30:07 +0200478 while ((de = readdir(dir))) {
Willy Tarreauee2663b2012-12-06 11:36:59 +0100479 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200480 if (stat(fp, &buf) != 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200481 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
482 err && *err ? *err : "", fp, strerror(errno));
Emeric Brunfc0421f2012-09-07 17:30:07 +0200483 cfgerr++;
484 continue;
485 }
486 if (!S_ISREG(buf.st_mode))
487 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100488 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, curproxy, NULL, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200489 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200490 closedir(dir);
491 return cfgerr;
492}
493
Thierry Fournier383085f2013-01-24 14:15:43 +0100494/* Make sure openssl opens /dev/urandom before the chroot. The work is only
495 * done once. Zero is returned if the operation fails. No error is returned
496 * if the random is said as not implemented, because we expect that openssl
497 * will use another method once needed.
498 */
499static int ssl_initialize_random()
500{
501 unsigned char random;
502 static int random_initialized = 0;
503
504 if (!random_initialized && RAND_bytes(&random, 1) != 0)
505 random_initialized = 1;
506
507 return random_initialized;
508}
509
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100510int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
511{
512 char thisline[65536];
513 FILE *f;
514 int linenum = 0;
515 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100516
Willy Tarreauad1731d2013-04-02 17:35:58 +0200517 if ((f = fopen(file, "r")) == NULL) {
518 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100519 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200520 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100521
522 while (fgets(thisline, sizeof(thisline), f) != NULL) {
523 int arg;
524 char *end;
525 char *args[MAX_LINE_ARGS + 1];
526 char *line = thisline;
527
528 linenum++;
529 end = line + strlen(line);
530 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
531 /* Check if we reached the limit and the last char is not \n.
532 * Watch out for the last line without the terminating '\n'!
533 */
Willy Tarreauad1731d2013-04-02 17:35:58 +0200534 memprintf(err, "line %d too long in file '%s', limit is %d characters",
535 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100536 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200537 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100538 }
539
540 /* skip leading spaces */
541 while (isspace(*line))
542 line++;
543
544 arg = 0;
545 args[arg] = line;
546
547 while (*line && arg < MAX_LINE_ARGS) {
548 if (*line == '#' || *line == '\n' || *line == '\r') {
549 /* end of string, end of loop */
550 *line = 0;
551 break;
552 }
553 else if (isspace(*line)) {
554 /* a non-escaped space is an argument separator */
555 *line++ = '\0';
556 while (isspace(*line))
557 line++;
558 args[++arg] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100559 }
560 else {
561 line++;
562 }
563 }
Willy Tarreauad1731d2013-04-02 17:35:58 +0200564
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100565 /* empty line */
566 if (!**args)
567 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100568
Willy Tarreauad1731d2013-04-02 17:35:58 +0200569 if (arg > 2) {
570 memprintf(err, "too many args on line %d in file '%s', only one SNI filter is supported (was '%s')",
571 linenum, file, args[2]);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100572 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200573 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100574 }
575
Willy Tarreauad1731d2013-04-02 17:35:58 +0200576 cfgerr = ssl_sock_load_cert_file(args[0], bind_conf, curproxy, arg > 1 ? args[1] : NULL, err);
577 if (cfgerr) {
578 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100579 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200580 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100581 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100582 fclose(f);
583 return cfgerr;
584}
585
Emeric Brunfc0421f2012-09-07 17:30:07 +0200586#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
587#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
588#endif
589
590#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
591#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
Willy Tarreau7d588ee2012-11-26 18:47:31 +0100592#define SSL_renegotiate_pending(arg) 0
Emeric Brunfc0421f2012-09-07 17:30:07 +0200593#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200594#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
595#define SSL_OP_SINGLE_ECDH_USE 0
596#endif
Emeric Brun2d0c4822012-10-02 13:45:20 +0200597#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
598#define SSL_OP_NO_TICKET 0
599#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200600#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
601#define SSL_OP_NO_COMPRESSION 0
602#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +0200603#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
604#define SSL_OP_NO_TLSv1_1 0
605#endif
606#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
607#define SSL_OP_NO_TLSv1_2 0
608#endif
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200609#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
610#define SSL_OP_SINGLE_DH_USE 0
611#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200612#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
613#define SSL_OP_SINGLE_ECDH_USE 0
614#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200615#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
616#define SSL_MODE_RELEASE_BUFFERS 0
617#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200618int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy *curproxy)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200619{
620 int cfgerr = 0;
621 int ssloptions =
622 SSL_OP_ALL | /* all known workarounds for bugs */
623 SSL_OP_NO_SSLv2 |
624 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200625 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +0200626 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +0200627 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
628 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200629 int sslmode =
630 SSL_MODE_ENABLE_PARTIAL_WRITE |
631 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
632 SSL_MODE_RELEASE_BUFFERS;
633
Thierry Fournier383085f2013-01-24 14:15:43 +0100634 /* Make sure openssl opens /dev/urandom before the chroot */
635 if (!ssl_initialize_random()) {
636 Alert("OpenSSL random data generator initialization failed.\n");
637 cfgerr++;
638 }
639
Emeric Brun89675492012-10-05 13:48:26 +0200640 if (bind_conf->ssl_options & BC_SSL_O_NO_SSLV3)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200641 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brun89675492012-10-05 13:48:26 +0200642 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV10)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200643 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun89675492012-10-05 13:48:26 +0200644 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV11)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200645 ssloptions |= SSL_OP_NO_TLSv1_1;
Emeric Brun89675492012-10-05 13:48:26 +0200646 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV12)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200647 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun89675492012-10-05 13:48:26 +0200648 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
Emeric Brun2d0c4822012-10-02 13:45:20 +0200649 ssloptions |= SSL_OP_NO_TICKET;
Emeric Brun2cb7ae52012-10-05 14:14:21 +0200650 if (bind_conf->ssl_options & BC_SSL_O_USE_SSLV3)
651 SSL_CTX_set_ssl_version(ctx, SSLv3_server_method());
652 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV10)
653 SSL_CTX_set_ssl_version(ctx, TLSv1_server_method());
654#if SSL_OP_NO_TLSv1_1
655 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV11)
656 SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method());
657#endif
658#if SSL_OP_NO_TLSv1_2
659 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV12)
660 SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method());
661#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200662
663 SSL_CTX_set_options(ctx, ssloptions);
664 SSL_CTX_set_mode(ctx, sslmode);
Emeric Brune64aef12012-09-21 13:15:06 +0200665 SSL_CTX_set_verify(ctx, bind_conf->verify ? bind_conf->verify : SSL_VERIFY_NONE, ssl_sock_verifycbk);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200666 if (bind_conf->verify & SSL_VERIFY_PEER) {
Emeric Brunfb510ea2012-10-05 12:00:26 +0200667 if (bind_conf->ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200668 /* load CAfile to verify */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200669 if (!SSL_CTX_load_verify_locations(ctx, bind_conf->ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200670 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200671 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200672 cfgerr++;
673 }
674 /* set CA names fo client cert request, function returns void */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200675 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(bind_conf->ca_file));
Emeric Brund94b3fe2012-09-20 18:23:56 +0200676 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200677#ifdef X509_V_FLAG_CRL_CHECK
Emeric Brunfb510ea2012-10-05 12:00:26 +0200678 if (bind_conf->crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200679 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
680
Emeric Brunfb510ea2012-10-05 12:00:26 +0200681 if (!store || !X509_STORE_load_locations(store, bind_conf->crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200682 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200683 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200684 cfgerr++;
685 }
Emeric Brun561e5742012-10-02 15:20:55 +0200686 else {
687 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
688 }
Emeric Brund94b3fe2012-09-20 18:23:56 +0200689 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200690#endif
Emeric Brun644cde02012-12-14 11:21:13 +0100691 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +0200692 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200693
Emeric Brun4f65bff2012-11-16 15:11:00 +0100694 if (global.tune.ssllifetime)
695 SSL_CTX_set_timeout(ctx, global.tune.ssllifetime);
696
Emeric Brunfc0421f2012-09-07 17:30:07 +0200697 shared_context_set_cache(ctx);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200698 if (bind_conf->ciphers &&
699 !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200700 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 +0200701 curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200702 cfgerr++;
703 }
704
705 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200706#ifdef OPENSSL_NPN_NEGOTIATED
707 if (bind_conf->npn_str)
708 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
709#endif
Willy Tarreauab861d32013-04-02 02:30:41 +0200710#ifdef OPENSSL_ALPN_NEGOTIATED
711 if (bind_conf->alpn_str)
712 SSL_CTX_set_alpn_advertised_cb(ctx, ssl_sock_advertise_alpn_protos, bind_conf);
713#endif
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200714
Emeric Brunfc0421f2012-09-07 17:30:07 +0200715#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
716 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200717 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200718#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200719#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emeric Brun6924ef82013-03-06 14:08:53 +0100720 {
Emeric Brun2b58d042012-09-20 17:10:03 +0200721 int i;
722 EC_KEY *ecdh;
723
Emeric Brun6924ef82013-03-06 14:08:53 +0100724 i = OBJ_sn2nid(bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE);
Emeric Brun2b58d042012-09-20 17:10:03 +0200725 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
726 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 +0100727 curproxy->id, bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE,
728 bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +0200729 cfgerr++;
730 }
731 else {
732 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
733 EC_KEY_free(ecdh);
734 }
735 }
736#endif
737
Emeric Brunfc0421f2012-09-07 17:30:07 +0200738 return cfgerr;
739}
740
Emeric Brun94324a42012-10-11 14:00:19 +0200741/* prepare ssl context from servers options. Returns an error count */
742int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
743{
744 int cfgerr = 0;
745 int options =
746 SSL_OP_ALL | /* all known workarounds for bugs */
747 SSL_OP_NO_SSLv2 |
748 SSL_OP_NO_COMPRESSION;
749 int mode =
750 SSL_MODE_ENABLE_PARTIAL_WRITE |
751 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
752 SSL_MODE_RELEASE_BUFFERS;
753
Thierry Fournier383085f2013-01-24 14:15:43 +0100754 /* Make sure openssl opens /dev/urandom before the chroot */
755 if (!ssl_initialize_random()) {
756 Alert("OpenSSL random data generator initialization failed.\n");
757 cfgerr++;
758 }
759
Emeric Brun94324a42012-10-11 14:00:19 +0200760 /* Initiate SSL context for current server */
761 srv->ssl_ctx.reused_sess = NULL;
762 if (srv->use_ssl)
763 srv->xprt = &ssl_sock;
764 if (srv->check.use_ssl)
765 srv->check.xprt = &ssl_sock;
766
767 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
768 if (!srv->ssl_ctx.ctx) {
769 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
770 proxy_type_str(curproxy), curproxy->id,
771 srv->id);
772 cfgerr++;
773 return cfgerr;
774 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200775 if (srv->ssl_ctx.client_crt) {
776 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
777 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
778 proxy_type_str(curproxy), curproxy->id,
779 srv->id, srv->ssl_ctx.client_crt);
780 cfgerr++;
781 }
782 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
783 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
784 proxy_type_str(curproxy), curproxy->id,
785 srv->id, srv->ssl_ctx.client_crt);
786 cfgerr++;
787 }
788 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
789 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
790 proxy_type_str(curproxy), curproxy->id,
791 srv->id, srv->ssl_ctx.client_crt);
792 cfgerr++;
793 }
794 }
Emeric Brun94324a42012-10-11 14:00:19 +0200795
796 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
797 options |= SSL_OP_NO_SSLv3;
798 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
799 options |= SSL_OP_NO_TLSv1;
800 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
801 options |= SSL_OP_NO_TLSv1_1;
802 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
803 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200804 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
805 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200806 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
807 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
808 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
809 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
810#if SSL_OP_NO_TLSv1_1
811 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
812 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
813#endif
814#if SSL_OP_NO_TLSv1_2
815 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
816 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
817#endif
818
819 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
820 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Emeric Brunef42d922012-10-11 16:11:36 +0200821 SSL_CTX_set_verify(srv->ssl_ctx.ctx, srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE, NULL);
822 if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
823 if (srv->ssl_ctx.ca_file) {
824 /* load CAfile to verify */
825 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
826 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
827 curproxy->id, srv->id,
828 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
829 cfgerr++;
830 }
831 }
832#ifdef X509_V_FLAG_CRL_CHECK
833 if (srv->ssl_ctx.crl_file) {
834 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
835
836 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
837 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
838 curproxy->id, srv->id,
839 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
840 cfgerr++;
841 }
842 else {
843 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
844 }
845 }
846#endif
847 }
848
Emeric Brun4f65bff2012-11-16 15:11:00 +0100849 if (global.tune.ssllifetime)
850 SSL_CTX_set_timeout(srv->ssl_ctx.ctx, global.tune.ssllifetime);
851
Emeric Brun94324a42012-10-11 14:00:19 +0200852 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
853 if (srv->ssl_ctx.ciphers &&
854 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
855 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
856 curproxy->id, srv->id,
857 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
858 cfgerr++;
859 }
860
861 return cfgerr;
862}
863
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200864/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200865 * be NULL, in which case nothing is done. Returns the number of errors
866 * encountered.
867 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200868int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200869{
870 struct ebmb_node *node;
871 struct sni_ctx *sni;
872 int err = 0;
873
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200874 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200875 return 0;
876
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200877 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200878 while (node) {
879 sni = ebmb_entry(node, struct sni_ctx, name);
880 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200881 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200882 node = ebmb_next(node);
883 }
884
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200885 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200886 while (node) {
887 sni = ebmb_entry(node, struct sni_ctx, name);
888 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200889 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200890 node = ebmb_next(node);
891 }
892 return err;
893}
894
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200895/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200896 * be NULL, in which case nothing is done. The default_ctx is nullified too.
897 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200898void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200899{
900 struct ebmb_node *node, *back;
901 struct sni_ctx *sni;
902
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200903 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200904 return;
905
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200906 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200907 while (node) {
908 sni = ebmb_entry(node, struct sni_ctx, name);
909 back = ebmb_next(node);
910 ebmb_delete(node);
911 if (!sni->order) /* only free the CTX on its first occurrence */
912 SSL_CTX_free(sni->ctx);
913 free(sni);
914 node = back;
915 }
916
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200917 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200918 while (node) {
919 sni = ebmb_entry(node, struct sni_ctx, name);
920 back = ebmb_next(node);
921 ebmb_delete(node);
922 if (!sni->order) /* only free the CTX on its first occurrence */
923 SSL_CTX_free(sni->ctx);
924 free(sni);
925 node = back;
926 }
927
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200928 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +0200929}
930
Emeric Brun46591952012-05-18 15:47:34 +0200931/*
932 * This function is called if SSL * context is not yet allocated. The function
933 * is designed to be called before any other data-layer operation and sets the
934 * handshake flag on the connection. It is safe to call it multiple times.
935 * It returns 0 on success and -1 in error case.
936 */
937static int ssl_sock_init(struct connection *conn)
938{
939 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200940 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200941 return 0;
942
Willy Tarreau20879a02012-12-03 16:32:10 +0100943 if (global.maxsslconn && sslconns >= global.maxsslconn) {
944 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +0200945 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100946 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200947
Emeric Brun46591952012-05-18 15:47:34 +0200948 /* If it is in client mode initiate SSL session
949 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100950 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200951 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100952 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +0100953 if (!conn->xprt_ctx) {
954 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +0200955 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100956 }
Emeric Brun46591952012-05-18 15:47:34 +0200957
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200958 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100959 if (objt_server(conn->target)->ssl_ctx.reused_sess)
960 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +0200961
962 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200963 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200964
965 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200966 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200967
968 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200969 return 0;
970 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100971 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200972 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100973 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +0100974 if (!conn->xprt_ctx) {
975 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +0200976 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100977 }
Emeric Brun46591952012-05-18 15:47:34 +0200978
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200979 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200980
981 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200982 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200983
Emeric Brune1f38db2012-09-03 20:36:47 +0200984 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200985 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +0200986
Emeric Brun46591952012-05-18 15:47:34 +0200987 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200988 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200989
990 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200991 return 0;
992 }
993 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +0100994 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +0200995 return -1;
996}
997
998
999/* This is the callback which is used when an SSL handshake is pending. It
1000 * updates the FD status if it wants some polling before being called again.
1001 * It returns 0 if it fails in a fatal way or needs to poll to go further,
1002 * otherwise it returns non-zero and removes itself from the connection's
1003 * flags (the bit is provided in <flag> by the caller).
1004 */
1005int ssl_sock_handshake(struct connection *conn, unsigned int flag)
1006{
1007 int ret;
1008
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001009 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001010 goto out_error;
1011
Emeric Brun674b7432012-11-08 19:21:55 +01001012 /* If we use SSL_do_handshake to process a reneg initiated by
1013 * the remote peer, it sometimes returns SSL_ERROR_SSL.
1014 * Usually SSL_write and SSL_read are used and process implicitly
1015 * the reneg handshake.
1016 * Here we use SSL_peek as a workaround for reneg.
1017 */
1018 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
1019 char c;
1020
1021 ret = SSL_peek(conn->xprt_ctx, &c, 1);
1022 if (ret <= 0) {
1023 /* handshake may have not been completed, let's find why */
1024 ret = SSL_get_error(conn->xprt_ctx, ret);
1025 if (ret == SSL_ERROR_WANT_WRITE) {
1026 /* SSL handshake needs to write, L4 connection may not be ready */
1027 __conn_sock_stop_recv(conn);
1028 __conn_sock_poll_send(conn);
1029 return 0;
1030 }
1031 else if (ret == SSL_ERROR_WANT_READ) {
1032 /* handshake may have been completed but we have
1033 * no more data to read.
1034 */
1035 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
1036 ret = 1;
1037 goto reneg_ok;
1038 }
1039 /* SSL handshake needs to read, L4 connection is ready */
1040 if (conn->flags & CO_FL_WAIT_L4_CONN)
1041 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1042 __conn_sock_stop_send(conn);
1043 __conn_sock_poll_recv(conn);
1044 return 0;
1045 }
1046 else if (ret == SSL_ERROR_SYSCALL) {
1047 /* if errno is null, then connection was successfully established */
1048 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1049 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001050 if (!conn->err_code) {
1051 if (!((SSL *)conn->xprt_ctx)->packet_length)
1052 if (!errno)
1053 conn->err_code = CO_ER_SSL_EMPTY;
1054 else
1055 conn->err_code = CO_ER_SSL_ABORT;
1056 else
1057 conn->err_code = CO_ER_SSL_HANDSHAKE;
1058 }
Emeric Brun674b7432012-11-08 19:21:55 +01001059 goto out_error;
1060 }
1061 else {
1062 /* Fail on all other handshake errors */
1063 /* Note: OpenSSL may leave unread bytes in the socket's
1064 * buffer, causing an RST to be emitted upon close() on
1065 * TCP sockets. We first try to drain possibly pending
1066 * data to avoid this as much as possible.
1067 */
1068 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Willy Tarreau20879a02012-12-03 16:32:10 +01001069 if (!conn->err_code)
1070 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01001071 goto out_error;
1072 }
1073 }
1074 /* read some data: consider handshake completed */
1075 goto reneg_ok;
1076 }
1077
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001078 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001079 if (ret != 1) {
1080 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001081 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001082
1083 if (ret == SSL_ERROR_WANT_WRITE) {
1084 /* SSL handshake needs to write, L4 connection may not be ready */
1085 __conn_sock_stop_recv(conn);
1086 __conn_sock_poll_send(conn);
1087 return 0;
1088 }
1089 else if (ret == SSL_ERROR_WANT_READ) {
1090 /* SSL handshake needs to read, L4 connection is ready */
1091 if (conn->flags & CO_FL_WAIT_L4_CONN)
1092 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1093 __conn_sock_stop_send(conn);
1094 __conn_sock_poll_recv(conn);
1095 return 0;
1096 }
Willy Tarreau89230192012-09-28 20:22:13 +02001097 else if (ret == SSL_ERROR_SYSCALL) {
1098 /* if errno is null, then connection was successfully established */
1099 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1100 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001101
1102 if (!((SSL *)conn->xprt_ctx)->packet_length)
1103 if (!errno)
1104 conn->err_code = CO_ER_SSL_EMPTY;
1105 else
1106 conn->err_code = CO_ER_SSL_ABORT;
1107 else
1108 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +02001109 goto out_error;
1110 }
Emeric Brun46591952012-05-18 15:47:34 +02001111 else {
1112 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02001113 /* Note: OpenSSL may leave unread bytes in the socket's
1114 * buffer, causing an RST to be emitted upon close() on
1115 * TCP sockets. We first try to drain possibly pending
1116 * data to avoid this as much as possible.
1117 */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01001118 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Willy Tarreau20879a02012-12-03 16:32:10 +01001119 if (!conn->err_code)
1120 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001121 goto out_error;
1122 }
1123 }
1124
Emeric Brun674b7432012-11-08 19:21:55 +01001125reneg_ok:
1126
Emeric Brun46591952012-05-18 15:47:34 +02001127 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001128 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001129 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +02001130 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001131 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1132 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001133
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001134 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001135 }
1136 }
1137
1138 /* The connection is now established at both layers, it's time to leave */
1139 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1140 return 1;
1141
1142 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001143 /* Clear openssl global errors stack */
1144 ERR_clear_error();
1145
Emeric Brun9fa89732012-10-04 17:09:56 +02001146 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001147 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1148 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1149 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001150 }
1151
Emeric Brun46591952012-05-18 15:47:34 +02001152 /* Fail on all other handshake errors */
1153 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001154 if (!conn->err_code)
1155 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001156 return 0;
1157}
1158
1159/* Receive up to <count> bytes from connection <conn>'s socket and store them
1160 * into buffer <buf>. The caller must ensure that <count> is always smaller
1161 * than the buffer's size. Only one call to recv() is performed, unless the
1162 * buffer wraps, in which case a second call may be performed. The connection's
1163 * flags are updated with whatever special event is detected (error, read0,
1164 * empty). The caller is responsible for taking care of those events and
1165 * avoiding the call if inappropriate. The function does not call the
1166 * connection's polling update function, so the caller is responsible for this.
1167 */
1168static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1169{
1170 int ret, done = 0;
1171 int try = count;
1172
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001173 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001174 goto out_error;
1175
1176 if (conn->flags & CO_FL_HANDSHAKE)
1177 /* a handshake was requested */
1178 return 0;
1179
1180 /* compute the maximum block size we can read at once. */
1181 if (buffer_empty(buf)) {
1182 /* let's realign the buffer to optimize I/O */
1183 buf->p = buf->data;
1184 }
1185 else if (buf->data + buf->o < buf->p &&
1186 buf->p + buf->i < buf->data + buf->size) {
1187 /* remaining space wraps at the end, with a moving limit */
1188 if (try > buf->data + buf->size - (buf->p + buf->i))
1189 try = buf->data + buf->size - (buf->p + buf->i);
1190 }
1191
1192 /* read the largest possible block. For this, we perform only one call
1193 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1194 * in which case we accept to do it once again. A new attempt is made on
1195 * EINTR too.
1196 */
1197 while (try) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001198 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001199 if (conn->flags & CO_FL_ERROR) {
1200 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001201 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001202 }
Emeric Brun46591952012-05-18 15:47:34 +02001203 if (ret > 0) {
1204 buf->i += ret;
1205 done += ret;
1206 if (ret < try)
1207 break;
1208 count -= ret;
1209 try = count;
1210 }
1211 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001212 ret = SSL_get_error(conn->xprt_ctx, ret);
1213 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001214 /* error on protocol or underlying transport */
1215 if ((ret != SSL_ERROR_SYSCALL)
1216 || (errno && (errno != EAGAIN)))
1217 conn->flags |= CO_FL_ERROR;
1218
Emeric Brun644cde02012-12-14 11:21:13 +01001219 /* Clear openssl global errors stack */
1220 ERR_clear_error();
1221 }
Emeric Brun46591952012-05-18 15:47:34 +02001222 goto read0;
1223 }
1224 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001225 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001226 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001227 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001228 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001229 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001230 break;
1231 }
1232 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001233 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1234 /* handshake is running, and it may need to re-enable read */
1235 conn->flags |= CO_FL_SSL_WAIT_HS;
1236 __conn_sock_want_recv(conn);
1237 break;
1238 }
Emeric Brun46591952012-05-18 15:47:34 +02001239 /* we need to poll for retry a read later */
1240 __conn_data_poll_recv(conn);
1241 break;
1242 }
1243 /* otherwise it's a real error */
1244 goto out_error;
1245 }
1246 }
1247 return done;
1248
1249 read0:
1250 conn_sock_read0(conn);
1251 return done;
1252 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001253 /* Clear openssl global errors stack */
1254 ERR_clear_error();
1255
Emeric Brun46591952012-05-18 15:47:34 +02001256 conn->flags |= CO_FL_ERROR;
1257 return done;
1258}
1259
1260
1261/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1262 * <flags> may contain MSG_MORE to make the system hold on without sending
1263 * data too fast, but this flag is ignored at the moment.
1264 * Only one call to send() is performed, unless the buffer wraps, in which case
1265 * a second call may be performed. The connection's flags are updated with
1266 * whatever special event is detected (error, empty). The caller is responsible
1267 * for taking care of those events and avoiding the call if inappropriate. The
1268 * function does not call the connection's polling update function, so the caller
1269 * is responsible for this.
1270 */
1271static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1272{
1273 int ret, try, done;
1274
1275 done = 0;
1276
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001277 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001278 goto out_error;
1279
1280 if (conn->flags & CO_FL_HANDSHAKE)
1281 /* a handshake was requested */
1282 return 0;
1283
1284 /* send the largest possible block. For this we perform only one call
1285 * to send() unless the buffer wraps and we exactly fill the first hunk,
1286 * in which case we accept to do it once again.
1287 */
1288 while (buf->o) {
1289 try = buf->o;
Willy Tarreaubfd59462013-02-21 07:46:09 +01001290
1291 if (global.tune.ssl_max_record && try > global.tune.ssl_max_record)
1292 try = global.tune.ssl_max_record;
1293
Emeric Brun46591952012-05-18 15:47:34 +02001294 /* outgoing data may wrap at the end */
1295 if (buf->data + try > buf->p)
1296 try = buf->data + try - buf->p;
1297
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001298 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001299 if (conn->flags & CO_FL_ERROR) {
1300 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001301 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001302 }
Emeric Brun46591952012-05-18 15:47:34 +02001303 if (ret > 0) {
1304 buf->o -= ret;
1305 done += ret;
1306
Willy Tarreau5fb38032012-12-16 19:39:09 +01001307 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001308 /* optimize data alignment in the buffer */
1309 buf->p = buf->data;
1310
1311 /* if the system buffer is full, don't insist */
1312 if (ret < try)
1313 break;
1314 }
1315 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001316 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001317 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001318 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1319 /* handshake is running, and it may need to re-enable write */
1320 conn->flags |= CO_FL_SSL_WAIT_HS;
1321 __conn_sock_want_send(conn);
1322 break;
1323 }
Emeric Brun46591952012-05-18 15:47:34 +02001324 /* we need to poll to retry a write later */
1325 __conn_data_poll_send(conn);
1326 break;
1327 }
1328 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001329 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001330 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001331 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001332 break;
1333 }
1334 goto out_error;
1335 }
1336 }
1337 return done;
1338
1339 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001340 /* Clear openssl global errors stack */
1341 ERR_clear_error();
1342
Emeric Brun46591952012-05-18 15:47:34 +02001343 conn->flags |= CO_FL_ERROR;
1344 return done;
1345}
1346
Emeric Brun46591952012-05-18 15:47:34 +02001347static void ssl_sock_close(struct connection *conn) {
1348
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001349 if (conn->xprt_ctx) {
1350 SSL_free(conn->xprt_ctx);
1351 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001352 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001353 }
Emeric Brun46591952012-05-18 15:47:34 +02001354}
1355
1356/* This function tries to perform a clean shutdown on an SSL connection, and in
1357 * any case, flags the connection as reusable if no handshake was in progress.
1358 */
1359static void ssl_sock_shutw(struct connection *conn, int clean)
1360{
1361 if (conn->flags & CO_FL_HANDSHAKE)
1362 return;
1363 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001364 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1365 /* Clear openssl global errors stack */
1366 ERR_clear_error();
1367 }
Emeric Brun46591952012-05-18 15:47:34 +02001368
1369 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001370 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001371}
1372
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001373/* used for logging, may be changed for a sample fetch later */
1374const char *ssl_sock_get_cipher_name(struct connection *conn)
1375{
1376 if (!conn->xprt && !conn->xprt_ctx)
1377 return NULL;
1378 return SSL_get_cipher_name(conn->xprt_ctx);
1379}
1380
1381/* used for logging, may be changed for a sample fetch later */
1382const char *ssl_sock_get_proto_version(struct connection *conn)
1383{
1384 if (!conn->xprt && !conn->xprt_ctx)
1385 return NULL;
1386 return SSL_get_version(conn->xprt_ctx);
1387}
1388
Willy Tarreau8d598402012-10-22 17:58:39 +02001389/* Extract a serial from a cert, and copy it to a chunk.
1390 * Returns 1 if serial is found and copied, 0 if no serial found and
1391 * -1 if output is not large enough.
1392 */
1393static int
1394ssl_sock_get_serial(X509 *crt, struct chunk *out)
1395{
1396 ASN1_INTEGER *serial;
1397
1398 serial = X509_get_serialNumber(crt);
1399 if (!serial)
1400 return 0;
1401
1402 if (out->size < serial->length)
1403 return -1;
1404
1405 memcpy(out->str, serial->data, serial->length);
1406 out->len = serial->length;
1407 return 1;
1408}
1409
Emeric Brunce5ad802012-10-22 14:11:22 +02001410
1411/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1412 * Returns 1 if serial is found and copied, 0 if no valid time found
1413 * and -1 if output is not large enough.
1414 */
1415static int
1416ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1417{
1418 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1419 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1420
1421 if (gentm->length < 12)
1422 return 0;
1423 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1424 return 0;
1425 if (out->size < gentm->length-2)
1426 return -1;
1427
1428 memcpy(out->str, gentm->data+2, gentm->length-2);
1429 out->len = gentm->length-2;
1430 return 1;
1431 }
1432 else if (tm->type == V_ASN1_UTCTIME) {
1433 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1434
1435 if (utctm->length < 10)
1436 return 0;
1437 if (utctm->data[0] >= 0x35)
1438 return 0;
1439 if (out->size < utctm->length)
1440 return -1;
1441
1442 memcpy(out->str, utctm->data, utctm->length);
1443 out->len = utctm->length;
1444 return 1;
1445 }
1446
1447 return 0;
1448}
1449
Emeric Brun87855892012-10-17 17:39:35 +02001450/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1451 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1452 */
1453static int
1454ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1455{
1456 X509_NAME_ENTRY *ne;
1457 int i, j, n;
1458 int cur = 0;
1459 const char *s;
1460 char tmp[128];
1461
1462 out->len = 0;
1463 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1464 if (pos < 0)
1465 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1466 else
1467 j = i;
1468
1469 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1470 n = OBJ_obj2nid(ne->object);
1471 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1472 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1473 s = tmp;
1474 }
1475
1476 if (chunk_strcasecmp(entry, s) != 0)
1477 continue;
1478
1479 if (pos < 0)
1480 cur--;
1481 else
1482 cur++;
1483
1484 if (cur != pos)
1485 continue;
1486
1487 if (ne->value->length > out->size)
1488 return -1;
1489
1490 memcpy(out->str, ne->value->data, ne->value->length);
1491 out->len = ne->value->length;
1492 return 1;
1493 }
1494
1495 return 0;
1496
1497}
1498
1499/* Extract and format full DN from a X509_NAME and copy result into a chunk
1500 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1501 */
1502static int
1503ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1504{
1505 X509_NAME_ENTRY *ne;
1506 int i, n, ln;
1507 int l = 0;
1508 const char *s;
1509 char *p;
1510 char tmp[128];
1511
1512 out->len = 0;
1513 p = out->str;
1514 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1515 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1516 n = OBJ_obj2nid(ne->object);
1517 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1518 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1519 s = tmp;
1520 }
1521 ln = strlen(s);
1522
1523 l += 1 + ln + 1 + ne->value->length;
1524 if (l > out->size)
1525 return -1;
1526 out->len = l;
1527
1528 *(p++)='/';
1529 memcpy(p, s, ln);
1530 p += ln;
1531 *(p++)='=';
1532 memcpy(p, ne->value->data, ne->value->length);
1533 p += ne->value->length;
1534 }
1535
1536 if (!out->len)
1537 return 0;
1538
1539 return 1;
1540}
1541
Willy Tarreau7875d092012-09-10 08:20:03 +02001542/***** Below are some sample fetching functions for ACL/patterns *****/
1543
Emeric Brune64aef12012-09-21 13:15:06 +02001544/* boolean, returns true if client cert was present */
1545static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001546smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1547 const struct arg *args, struct sample *smp)
Emeric Brune64aef12012-09-21 13:15:06 +02001548{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001549 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001550 return 0;
1551
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001552 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001553 smp->flags |= SMP_F_MAY_CHANGE;
1554 return 0;
1555 }
1556
1557 smp->flags = 0;
1558 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001559 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001560
1561 return 1;
1562}
1563
Willy Tarreau8d598402012-10-22 17:58:39 +02001564/* bin, returns serial in a binary chunk */
1565static int
1566smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1567 const struct arg *args, struct sample *smp)
1568{
1569 X509 *crt = NULL;
1570 int ret = 0;
1571 struct chunk *smp_trash;
1572
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001573 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001574 return 0;
1575
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001576 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001577 smp->flags |= SMP_F_MAY_CHANGE;
1578 return 0;
1579 }
1580
1581 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001582 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001583 if (!crt)
1584 goto out;
1585
Willy Tarreau47ca5452012-12-23 20:22:19 +01001586 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001587 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1588 goto out;
1589
1590 smp->data.str = *smp_trash;
1591 smp->type = SMP_T_BIN;
1592 ret = 1;
1593out:
1594 if (crt)
1595 X509_free(crt);
1596 return ret;
1597}
Emeric Brune64aef12012-09-21 13:15:06 +02001598
Emeric Brunce5ad802012-10-22 14:11:22 +02001599/*str, returns notafter date in ASN1_UTCTIME format */
1600static int
1601smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1602 const struct arg *args, struct sample *smp)
1603{
1604 X509 *crt = NULL;
1605 int ret = 0;
1606 struct chunk *smp_trash;
1607
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001608 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001609 return 0;
1610
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001611 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001612 smp->flags |= SMP_F_MAY_CHANGE;
1613 return 0;
1614 }
1615
1616 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001617 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001618 if (!crt)
1619 goto out;
1620
Willy Tarreau47ca5452012-12-23 20:22:19 +01001621 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001622 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1623 goto out;
1624
1625 smp->data.str = *smp_trash;
1626 smp->type = SMP_T_STR;
1627 ret = 1;
1628out:
1629 if (crt)
1630 X509_free(crt);
1631 return ret;
1632}
1633
Emeric Brun87855892012-10-17 17:39:35 +02001634/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1635static int
1636smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1637 const struct arg *args, struct sample *smp)
1638{
1639 X509 *crt = NULL;
1640 X509_NAME *name;
1641 int ret = 0;
1642 struct chunk *smp_trash;
1643
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001644 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001645 return 0;
1646
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001647 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001648 smp->flags |= SMP_F_MAY_CHANGE;
1649 return 0;
1650 }
1651
1652 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001653 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001654 if (!crt)
1655 goto out;
1656
1657 name = X509_get_issuer_name(crt);
1658 if (!name)
1659 goto out;
1660
Willy Tarreau47ca5452012-12-23 20:22:19 +01001661 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001662 if (args && args[0].type == ARGT_STR) {
1663 int pos = 1;
1664
1665 if (args[1].type == ARGT_SINT)
1666 pos = args[1].data.sint;
1667 else if (args[1].type == ARGT_UINT)
1668 pos =(int)args[1].data.uint;
1669
1670 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1671 goto out;
1672 }
1673 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1674 goto out;
1675
1676 smp->type = SMP_T_STR;
1677 smp->data.str = *smp_trash;
1678 ret = 1;
1679out:
1680 if (crt)
1681 X509_free(crt);
1682 return ret;
1683}
1684
Emeric Brunce5ad802012-10-22 14:11:22 +02001685/*str, returns notbefore date in ASN1_UTCTIME format */
1686static int
1687smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1688 const struct arg *args, struct sample *smp)
1689{
1690 X509 *crt = NULL;
1691 int ret = 0;
1692 struct chunk *smp_trash;
1693
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001694 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001695 return 0;
1696
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001697 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001698 smp->flags |= SMP_F_MAY_CHANGE;
1699 return 0;
1700 }
1701
1702 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001703 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001704 if (!crt)
1705 goto out;
1706
Willy Tarreau47ca5452012-12-23 20:22:19 +01001707 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001708 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1709 goto out;
1710
1711 smp->data.str = *smp_trash;
1712 smp->type = SMP_T_STR;
1713 ret = 1;
1714out:
1715 if (crt)
1716 X509_free(crt);
1717 return ret;
1718}
1719
Emeric Brun87855892012-10-17 17:39:35 +02001720/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1721static int
1722smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1723 const struct arg *args, struct sample *smp)
1724{
1725 X509 *crt = NULL;
1726 X509_NAME *name;
1727 int ret = 0;
1728 struct chunk *smp_trash;
1729
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001730 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001731 return 0;
1732
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001733 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001734 smp->flags |= SMP_F_MAY_CHANGE;
1735 return 0;
1736 }
1737
1738 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001739 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001740 if (!crt)
1741 goto out;
1742
1743 name = X509_get_subject_name(crt);
1744 if (!name)
1745 goto out;
1746
Willy Tarreau47ca5452012-12-23 20:22:19 +01001747 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001748 if (args && args[0].type == ARGT_STR) {
1749 int pos = 1;
1750
1751 if (args[1].type == ARGT_SINT)
1752 pos = args[1].data.sint;
1753 else if (args[1].type == ARGT_UINT)
1754 pos =(int)args[1].data.uint;
1755
1756 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1757 goto out;
1758 }
1759 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1760 goto out;
1761
1762 smp->type = SMP_T_STR;
1763 smp->data.str = *smp_trash;
1764 ret = 1;
1765out:
1766 if (crt)
1767 X509_free(crt);
1768 return ret;
1769}
Emeric Brun9143d372012-12-20 15:44:16 +01001770
1771/* integer, returns true if current session use a client certificate */
1772static int
1773smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1774 const struct arg *args, struct sample *smp)
1775{
1776 X509 *crt;
1777
1778 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
1779 return 0;
1780
1781 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
1782 smp->flags |= SMP_F_MAY_CHANGE;
1783 return 0;
1784 }
1785
1786 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
1787 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
1788 if (crt) {
1789 X509_free(crt);
1790 }
1791
1792 smp->type = SMP_T_BOOL;
1793 smp->data.uint = (crt != NULL);
1794 return 1;
1795}
1796
Emeric Bruna7359fd2012-10-17 15:03:11 +02001797/* integer, returns the client certificate version */
1798static int
1799smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1800 const struct arg *args, struct sample *smp)
1801{
1802 X509 *crt;
1803
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001804 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001805 return 0;
1806
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001807 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001808 smp->flags |= SMP_F_MAY_CHANGE;
1809 return 0;
1810 }
1811
1812 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001813 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001814 if (!crt)
1815 return 0;
1816
1817 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1818 X509_free(crt);
1819 smp->type = SMP_T_UINT;
1820
1821 return 1;
1822}
1823
Emeric Brun7f56e742012-10-19 18:15:40 +02001824/* str, returns the client certificate sig alg */
1825static int
1826smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1827 const struct arg *args, struct sample *smp)
1828{
1829 X509 *crt;
1830 int nid;
1831
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001832 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02001833 return 0;
1834
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001835 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02001836 smp->flags |= SMP_F_MAY_CHANGE;
1837 return 0;
1838 }
1839
1840 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001841 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02001842 if (!crt)
1843 return 0;
1844
1845 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1846
1847 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1848 if (!smp->data.str.str)
1849 return 0;
1850
1851 smp->type = SMP_T_CSTR;
1852 smp->data.str.len = strlen(smp->data.str.str);
1853 X509_free(crt);
1854
1855 return 1;
1856}
1857
Emeric Brun521a0112012-10-22 12:22:55 +02001858/* str, returns the client certificate key alg */
1859static int
1860smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1861 const struct arg *args, struct sample *smp)
1862{
1863 X509 *crt;
1864 int nid;
1865
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001866 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02001867 return 0;
1868
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001869 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02001870 smp->flags |= SMP_F_MAY_CHANGE;
1871 return 0;
1872 }
1873
1874 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001875 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02001876 if (!crt)
1877 return 0;
1878
1879 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1880
1881 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1882 if (!smp->data.str.str)
1883 return 0;
1884
1885 smp->type = SMP_T_CSTR;
1886 smp->data.str.len = strlen(smp->data.str.str);
1887 X509_free(crt);
1888
1889 return 1;
1890}
1891
Emeric Brun2525b6b2012-10-18 15:59:43 +02001892/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02001893static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001894smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau7875d092012-09-10 08:20:03 +02001895 const struct arg *args, struct sample *smp)
1896{
1897 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001898 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02001899 return 1;
1900}
1901
Emeric Brun2525b6b2012-10-18 15:59:43 +02001902/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02001903static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001904smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1905 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02001906{
1907#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1908 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001909 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock) &&
1910 l4->si[0].conn->xprt_ctx &&
1911 SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02001912 return 1;
1913#else
1914 return 0;
1915#endif
1916}
1917
Willy Tarreau8d598402012-10-22 17:58:39 +02001918/* bin, returns serial in a binary chunk */
1919static int
1920smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1921 const struct arg *args, struct sample *smp)
1922{
1923 X509 *crt = NULL;
1924 int ret = 0;
1925 struct chunk *smp_trash;
1926
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001927 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001928 return 0;
1929
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001930 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001931 smp->flags |= SMP_F_MAY_CHANGE;
1932 return 0;
1933 }
1934
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001935 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001936 if (!crt)
1937 goto out;
1938
Willy Tarreau47ca5452012-12-23 20:22:19 +01001939 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001940 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1941 goto out;
1942
1943 smp->data.str = *smp_trash;
1944 smp->type = SMP_T_BIN;
1945 ret = 1;
1946out:
1947 return ret;
1948}
Emeric Brunce5ad802012-10-22 14:11:22 +02001949/*str, returns notafter date in ASN1_UTCTIME format */
1950static int
1951smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1952 const struct arg *args, struct sample *smp)
1953{
1954 X509 *crt = NULL;
1955 int ret = 0;
1956 struct chunk *smp_trash;
1957
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001958 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001959 return 0;
1960
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001961 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001962 smp->flags |= SMP_F_MAY_CHANGE;
1963 return 0;
1964 }
1965
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001966 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001967 if (!crt)
1968 goto out;
1969
Willy Tarreau47ca5452012-12-23 20:22:19 +01001970 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001971 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1972 goto out;
1973
1974 smp->data.str = *smp_trash;
1975 smp->type = SMP_T_STR;
1976 ret = 1;
1977out:
1978 return ret;
1979}
1980
1981/*str, returns notbefore date in ASN1_UTCTIME format */
1982static int
1983smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1984 const struct arg *args, struct sample *smp)
1985{
1986 X509 *crt = NULL;
1987 int ret = 0;
1988 struct chunk *smp_trash;
1989
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001990 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001991 return 0;
1992
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001993 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001994 smp->flags |= SMP_F_MAY_CHANGE;
1995 return 0;
1996 }
1997
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001998 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001999 if (!crt)
2000 goto out;
2001
Willy Tarreau47ca5452012-12-23 20:22:19 +01002002 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002003 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
2004 goto out;
2005
2006 smp->data.str = *smp_trash;
2007 smp->type = SMP_T_STR;
2008 ret = 1;
2009out:
2010 return ret;
2011}
Willy Tarreau8d598402012-10-22 17:58:39 +02002012
Emeric Bruna7359fd2012-10-17 15:03:11 +02002013/* integer, returns the frontend certificate version */
2014static int
2015smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2016 const struct arg *args, struct sample *smp)
2017{
2018 X509 *crt;
2019
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002020 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002021 return 0;
2022
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002023 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002024 smp->flags |= SMP_F_MAY_CHANGE;
2025 return 0;
2026 }
2027
2028 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002029 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002030 if (!crt)
2031 return 0;
2032
2033 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2034 smp->type = SMP_T_UINT;
2035
2036 return 1;
2037}
2038
Emeric Brun7f56e742012-10-19 18:15:40 +02002039/* str, returns the client certificate sig alg */
2040static int
2041smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2042 const struct arg *args, struct sample *smp)
2043{
2044 X509 *crt;
2045 int nid;
2046
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002047 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02002048 return 0;
2049
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002050 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002051 smp->flags |= SMP_F_MAY_CHANGE;
2052 return 0;
2053 }
2054
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002055 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002056 if (!crt)
2057 return 0;
2058
2059 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2060
2061 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2062 if (!smp->data.str.str)
2063 return 0;
2064
2065 smp->type = SMP_T_CSTR;
2066 smp->data.str.len = strlen(smp->data.str.str);
2067
2068 return 1;
2069}
2070
Emeric Brun521a0112012-10-22 12:22:55 +02002071/* str, returns the client certificate key alg */
2072static int
2073smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2074 const struct arg *args, struct sample *smp)
2075{
2076 X509 *crt;
2077 int nid;
2078
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002079 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002080 return 0;
2081
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002082 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002083 smp->flags |= SMP_F_MAY_CHANGE;
2084 return 0;
2085 }
2086
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002087 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002088 if (!crt)
2089 return 0;
2090
2091 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2092
2093 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2094 if (!smp->data.str.str)
2095 return 0;
2096
2097 smp->type = SMP_T_CSTR;
2098 smp->data.str.len = strlen(smp->data.str.str);
2099
2100 return 1;
2101}
2102
Emeric Brun87855892012-10-17 17:39:35 +02002103/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2104static int
2105smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2106 const struct arg *args, struct sample *smp)
2107{
2108 X509 *crt = NULL;
2109 X509_NAME *name;
2110 int ret = 0;
2111 struct chunk *smp_trash;
2112
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002113 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002114 return 0;
2115
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002116 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002117 smp->flags |= SMP_F_MAY_CHANGE;
2118 return 0;
2119 }
2120
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002121 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002122 if (!crt)
2123 goto out;
2124
2125 name = X509_get_issuer_name(crt);
2126 if (!name)
2127 goto out;
2128
Willy Tarreau47ca5452012-12-23 20:22:19 +01002129 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002130 if (args && args[0].type == ARGT_STR) {
2131 int pos = 1;
2132
2133 if (args[1].type == ARGT_SINT)
2134 pos = args[1].data.sint;
2135 else if (args[1].type == ARGT_UINT)
2136 pos =(int)args[1].data.uint;
2137
2138 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2139 goto out;
2140 }
2141 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2142 goto out;
2143
2144 smp->type = SMP_T_STR;
2145 smp->data.str = *smp_trash;
2146 ret = 1;
2147out:
2148 return ret;
2149}
2150
2151/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2152static int
2153smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2154 const struct arg *args, struct sample *smp)
2155{
2156 X509 *crt = NULL;
2157 X509_NAME *name;
2158 int ret = 0;
2159 struct chunk *smp_trash;
2160
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002161 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002162 return 0;
2163
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002164 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002165 smp->flags |= SMP_F_MAY_CHANGE;
2166 return 0;
2167 }
2168
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002169 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002170 if (!crt)
2171 goto out;
2172
2173 name = X509_get_subject_name(crt);
2174 if (!name)
2175 goto out;
2176
Willy Tarreau47ca5452012-12-23 20:22:19 +01002177 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002178 if (args && args[0].type == ARGT_STR) {
2179 int pos = 1;
2180
2181 if (args[1].type == ARGT_SINT)
2182 pos = args[1].data.sint;
2183 else if (args[1].type == ARGT_UINT)
2184 pos =(int)args[1].data.uint;
2185
2186 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2187 goto out;
2188 }
2189 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2190 goto out;
2191
2192 smp->type = SMP_T_STR;
2193 smp->data.str = *smp_trash;
2194 ret = 1;
2195out:
2196 return ret;
2197}
2198
Emeric Brun589fcad2012-10-16 14:13:26 +02002199static int
2200smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2201 const struct arg *args, struct sample *smp)
2202{
2203 smp->flags = 0;
2204
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002205 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002206 return 0;
2207
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002208 smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002209 if (!smp->data.str.str)
2210 return 0;
2211
2212 smp->type = SMP_T_CSTR;
2213 smp->data.str.len = strlen(smp->data.str.str);
2214
2215 return 1;
2216}
2217
2218static int
2219smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2220 const struct arg *args, struct sample *smp)
2221{
2222 smp->flags = 0;
2223
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002224 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002225 return 0;
2226
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002227 if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
Emeric Brun589fcad2012-10-16 14:13:26 +02002228 return 0;
2229
2230 smp->type = SMP_T_UINT;
2231
2232 return 1;
2233}
2234
2235static int
2236smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2237 const struct arg *args, struct sample *smp)
2238{
2239 smp->flags = 0;
2240
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002241 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002242 return 0;
2243
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002244 smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002245 if (!smp->data.uint)
2246 return 0;
2247
2248 smp->type = SMP_T_UINT;
2249
2250 return 1;
2251}
2252
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002253#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002254static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002255smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2256 const struct arg *args, struct sample *smp)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002257{
Willy Tarreaua33c6542012-10-15 13:19:06 +02002258 smp->flags = 0;
2259 smp->type = SMP_T_CSTR;
2260
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002261 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002262 return 0;
2263
2264 smp->data.str.str = NULL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002265 SSL_get0_next_proto_negotiated(l4->si[0].conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002266 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2267
2268 if (!smp->data.str.str)
2269 return 0;
2270
2271 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002272}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002273#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002274
Willy Tarreauab861d32013-04-02 02:30:41 +02002275#ifdef OPENSSL_ALPN_NEGOTIATED
2276static int
2277smp_fetch_ssl_fc_alpn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2278 const struct arg *args, struct sample *smp)
2279{
2280 smp->flags = 0;
2281 smp->type = SMP_T_CSTR;
2282
2283 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
2284 return 0;
2285
2286 smp->data.str.str = NULL;
2287 SSL_get0_alpn_negotiated(l4->si[0].conn->xprt_ctx,
2288 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2289
2290 if (!smp->data.str.str)
2291 return 0;
2292
2293 return 1;
2294}
2295#endif
2296
Willy Tarreaua33c6542012-10-15 13:19:06 +02002297static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002298smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2299 const struct arg *args, struct sample *smp)
2300{
2301 smp->flags = 0;
2302
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002303 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002304 return 0;
2305
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002306 smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002307 if (!smp->data.str.str)
2308 return 0;
2309
2310 smp->type = SMP_T_CSTR;
2311 smp->data.str.len = strlen(smp->data.str.str);
2312
2313 return 1;
2314}
2315
2316static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002317smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2318 const struct arg *args, struct sample *smp)
2319{
2320#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2321 SSL_SESSION *sess;
2322
2323 smp->flags = 0;
2324 smp->type = SMP_T_CBIN;
2325
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002326 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunfe68f682012-10-16 14:59:28 +02002327 return 0;
2328
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002329 sess = SSL_get_session(l4->si[0].conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002330 if (!sess)
2331 return 0;
2332
2333 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2334 if (!smp->data.str.str || !&smp->data.str.len)
2335 return 0;
2336
2337 return 1;
2338#else
2339 return 0;
2340#endif
2341}
2342
2343static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002344smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2345 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02002346{
2347#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2348 smp->flags = 0;
2349 smp->type = SMP_T_CSTR;
2350
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002351 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau7875d092012-09-10 08:20:03 +02002352 return 0;
2353
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002354 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 +02002355 if (!smp->data.str.str)
2356 return 0;
2357
Willy Tarreau7875d092012-09-10 08:20:03 +02002358 smp->data.str.len = strlen(smp->data.str.str);
2359 return 1;
2360#else
2361 return 0;
2362#endif
2363}
2364
Emeric Brun2525b6b2012-10-18 15:59:43 +02002365/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002366static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002367smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002368 const struct arg *args, struct sample *smp)
2369{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002370 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002371 return 0;
2372
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002373 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002374 smp->flags = SMP_F_MAY_CHANGE;
2375 return 0;
2376 }
2377
2378 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002379 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002380 smp->flags = 0;
2381
2382 return 1;
2383}
2384
Emeric Brun2525b6b2012-10-18 15:59:43 +02002385/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002386static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002387smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002388 const struct arg *args, struct sample *smp)
2389{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002390 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002391 return 0;
2392
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002393 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002394 smp->flags = SMP_F_MAY_CHANGE;
2395 return 0;
2396 }
2397
2398 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002399 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002400 smp->flags = 0;
2401
2402 return 1;
2403}
2404
Emeric Brun2525b6b2012-10-18 15:59:43 +02002405/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002406static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002407smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2408 const struct arg *args, struct sample *smp)
Emeric Brunf282a812012-09-21 15:27:54 +02002409{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002410 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002411 return 0;
2412
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002413 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002414 smp->flags = SMP_F_MAY_CHANGE;
2415 return 0;
2416 }
2417
2418 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002419 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002420 smp->flags = 0;
2421
2422 return 1;
2423}
2424
Emeric Brun2525b6b2012-10-18 15:59:43 +02002425/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002426static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002427smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2428 const struct arg *args, struct sample *smp)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002429{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002430 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002431 return 0;
2432
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002433 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002434 smp->flags = SMP_F_MAY_CHANGE;
2435 return 0;
2436 }
2437
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002438 if (!l4->si[0].conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002439 return 0;
2440
2441 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002442 smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002443 smp->flags = 0;
2444
2445 return 1;
2446}
2447
Emeric Brunfb510ea2012-10-05 12:00:26 +02002448/* parse the "ca-file" bind keyword */
2449static 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 +02002450{
2451 if (!*args[cur_arg + 1]) {
2452 if (err)
2453 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2454 return ERR_ALERT | ERR_FATAL;
2455 }
2456
Emeric Brunef42d922012-10-11 16:11:36 +02002457 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2458 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2459 else
2460 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002461
Emeric Brund94b3fe2012-09-20 18:23:56 +02002462 return 0;
2463}
2464
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002465/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002466static 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 +02002467{
2468 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002469 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002470 return ERR_ALERT | ERR_FATAL;
2471 }
2472
Emeric Brun76d88952012-10-05 15:47:31 +02002473 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002474 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002475 return 0;
2476}
2477
2478/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002479static 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 +02002480{
Emeric Brunc8e8d122012-10-02 18:42:10 +02002481 char path[PATH_MAX];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002482 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002483 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002484 return ERR_ALERT | ERR_FATAL;
2485 }
2486
Emeric Brunc8e8d122012-10-02 18:42:10 +02002487 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
2488 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > PATH_MAX) {
2489 memprintf(err, "'%s' : path too long", args[cur_arg]);
2490 return ERR_ALERT | ERR_FATAL;
2491 }
2492 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2493 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2494 return ERR_ALERT | ERR_FATAL;
2495
2496 return 0;
2497 }
2498
Willy Tarreau4348fad2012-09-20 16:48:07 +02002499 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002500 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002501
2502 return 0;
2503}
2504
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002505/* parse the "crt-list" bind keyword */
2506static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2507{
2508 if (!*args[cur_arg + 1]) {
2509 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
2510 return ERR_ALERT | ERR_FATAL;
2511 }
2512
Willy Tarreauad1731d2013-04-02 17:35:58 +02002513 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
2514 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002515 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02002516 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002517
2518 return 0;
2519}
2520
Emeric Brunfb510ea2012-10-05 12:00:26 +02002521/* parse the "crl-file" bind keyword */
2522static 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 +02002523{
Emeric Brun051cdab2012-10-02 19:25:50 +02002524#ifndef X509_V_FLAG_CRL_CHECK
2525 if (err)
2526 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2527 return ERR_ALERT | ERR_FATAL;
2528#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002529 if (!*args[cur_arg + 1]) {
2530 if (err)
2531 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2532 return ERR_ALERT | ERR_FATAL;
2533 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002534
Emeric Brunef42d922012-10-11 16:11:36 +02002535 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2536 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2537 else
2538 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002539
Emeric Brun2b58d042012-09-20 17:10:03 +02002540 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002541#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002542}
2543
2544/* parse the "ecdhe" bind keyword keywords */
2545static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2546{
2547#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2548 if (err)
2549 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2550 return ERR_ALERT | ERR_FATAL;
2551#elif defined(OPENSSL_NO_ECDH)
2552 if (err)
2553 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2554 return ERR_ALERT | ERR_FATAL;
2555#else
2556 if (!*args[cur_arg + 1]) {
2557 if (err)
2558 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2559 return ERR_ALERT | ERR_FATAL;
2560 }
2561
2562 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002563
2564 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002565#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002566}
2567
Emeric Brun81c00f02012-09-21 14:31:21 +02002568/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2569static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2570{
2571 int code;
2572 char *p = args[cur_arg + 1];
2573 unsigned long long *ignerr = &conf->crt_ignerr;
2574
2575 if (!*p) {
2576 if (err)
2577 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2578 return ERR_ALERT | ERR_FATAL;
2579 }
2580
2581 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2582 ignerr = &conf->ca_ignerr;
2583
2584 if (strcmp(p, "all") == 0) {
2585 *ignerr = ~0ULL;
2586 return 0;
2587 }
2588
2589 while (p) {
2590 code = atoi(p);
2591 if ((code <= 0) || (code > 63)) {
2592 if (err)
2593 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2594 args[cur_arg], code, args[cur_arg + 1]);
2595 return ERR_ALERT | ERR_FATAL;
2596 }
2597 *ignerr |= 1ULL << code;
2598 p = strchr(p, ',');
2599 if (p)
2600 p++;
2601 }
2602
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002603 return 0;
2604}
2605
2606/* parse the "force-sslv3" bind keyword */
2607static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2608{
2609 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2610 return 0;
2611}
2612
2613/* parse the "force-tlsv10" bind keyword */
2614static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2615{
2616 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002617 return 0;
2618}
2619
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002620/* parse the "force-tlsv11" bind keyword */
2621static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2622{
2623#if SSL_OP_NO_TLSv1_1
2624 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
2625 return 0;
2626#else
2627 if (err)
2628 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
2629 return ERR_ALERT | ERR_FATAL;
2630#endif
2631}
2632
2633/* parse the "force-tlsv12" bind keyword */
2634static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2635{
2636#if SSL_OP_NO_TLSv1_2
2637 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
2638 return 0;
2639#else
2640 if (err)
2641 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
2642 return ERR_ALERT | ERR_FATAL;
2643#endif
2644}
2645
2646
Emeric Brun2d0c4822012-10-02 13:45:20 +02002647/* parse the "no-tls-tickets" bind keyword */
2648static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2649{
Emeric Brun89675492012-10-05 13:48:26 +02002650 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02002651 return 0;
2652}
2653
Emeric Brun2d0c4822012-10-02 13:45:20 +02002654
Emeric Brun9b3009b2012-10-05 11:55:06 +02002655/* parse the "no-sslv3" bind keyword */
2656static 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 +02002657{
Emeric Brun89675492012-10-05 13:48:26 +02002658 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002659 return 0;
2660}
2661
Emeric Brun9b3009b2012-10-05 11:55:06 +02002662/* parse the "no-tlsv10" bind keyword */
2663static 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 +02002664{
Emeric Brun89675492012-10-05 13:48:26 +02002665 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002666 return 0;
2667}
2668
Emeric Brun9b3009b2012-10-05 11:55:06 +02002669/* parse the "no-tlsv11" bind keyword */
2670static 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 +02002671{
Emeric Brun89675492012-10-05 13:48:26 +02002672 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002673 return 0;
2674}
2675
Emeric Brun9b3009b2012-10-05 11:55:06 +02002676/* parse the "no-tlsv12" bind keyword */
2677static 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 +02002678{
Emeric Brun89675492012-10-05 13:48:26 +02002679 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002680 return 0;
2681}
2682
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002683/* parse the "npn" bind keyword */
2684static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2685{
2686#ifdef OPENSSL_NPN_NEGOTIATED
2687 char *p1, *p2;
2688
2689 if (!*args[cur_arg + 1]) {
2690 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
2691 return ERR_ALERT | ERR_FATAL;
2692 }
2693
2694 free(conf->npn_str);
2695
2696 /* the NPN string is built as a suite of (<len> <name>)* */
2697 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
2698 conf->npn_str = calloc(1, conf->npn_len);
2699 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
2700
2701 /* replace commas with the name length */
2702 p1 = conf->npn_str;
2703 p2 = p1 + 1;
2704 while (1) {
2705 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
2706 if (!p2)
2707 p2 = p1 + 1 + strlen(p1 + 1);
2708
2709 if (p2 - (p1 + 1) > 255) {
2710 *p2 = '\0';
2711 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2712 return ERR_ALERT | ERR_FATAL;
2713 }
2714
2715 *p1 = p2 - (p1 + 1);
2716 p1 = p2;
2717
2718 if (!*p2)
2719 break;
2720
2721 *(p2++) = '\0';
2722 }
2723 return 0;
2724#else
2725 if (err)
2726 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
2727 return ERR_ALERT | ERR_FATAL;
2728#endif
2729}
2730
Willy Tarreauab861d32013-04-02 02:30:41 +02002731/* parse the "alpn" bind keyword */
2732static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2733{
2734#ifdef OPENSSL_ALPN_NEGOTIATED
2735 char *p1, *p2;
2736
2737 if (!*args[cur_arg + 1]) {
2738 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
2739 return ERR_ALERT | ERR_FATAL;
2740 }
2741
2742 free(conf->alpn_str);
2743
2744 /* the ALPN string is built as a suite of (<len> <name>)* */
2745 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
2746 conf->alpn_str = calloc(1, conf->alpn_len);
2747 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
2748
2749 /* replace commas with the name length */
2750 p1 = conf->alpn_str;
2751 p2 = p1 + 1;
2752 while (1) {
2753 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
2754 if (!p2)
2755 p2 = p1 + 1 + strlen(p1 + 1);
2756
2757 if (p2 - (p1 + 1) > 255) {
2758 *p2 = '\0';
2759 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2760 return ERR_ALERT | ERR_FATAL;
2761 }
2762
2763 *p1 = p2 - (p1 + 1);
2764 p1 = p2;
2765
2766 if (!*p2)
2767 break;
2768
2769 *(p2++) = '\0';
2770 }
2771 return 0;
2772#else
2773 if (err)
2774 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
2775 return ERR_ALERT | ERR_FATAL;
2776#endif
2777}
2778
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002779/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002780static 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 +02002781{
Willy Tarreau81796be2012-09-22 19:11:47 +02002782 struct listener *l;
2783
Willy Tarreau4348fad2012-09-20 16:48:07 +02002784 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02002785
2786 if (global.listen_default_ciphers && !conf->ciphers)
2787 conf->ciphers = strdup(global.listen_default_ciphers);
2788
Willy Tarreau81796be2012-09-22 19:11:47 +02002789 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002790 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02002791
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002792 return 0;
2793}
2794
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002795/* parse the "strict-sni" bind keyword */
2796static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2797{
2798 conf->strict_sni = 1;
2799 return 0;
2800}
2801
Emeric Brund94b3fe2012-09-20 18:23:56 +02002802/* parse the "verify" bind keyword */
2803static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2804{
2805 if (!*args[cur_arg + 1]) {
2806 if (err)
2807 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
2808 return ERR_ALERT | ERR_FATAL;
2809 }
2810
2811 if (strcmp(args[cur_arg + 1], "none") == 0)
2812 conf->verify = SSL_VERIFY_NONE;
2813 else if (strcmp(args[cur_arg + 1], "optional") == 0)
2814 conf->verify = SSL_VERIFY_PEER;
2815 else if (strcmp(args[cur_arg + 1], "required") == 0)
2816 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2817 else {
2818 if (err)
2819 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
2820 args[cur_arg], args[cur_arg + 1]);
2821 return ERR_ALERT | ERR_FATAL;
2822 }
2823
2824 return 0;
2825}
2826
Willy Tarreau92faadf2012-10-10 23:04:25 +02002827/************** "server" keywords ****************/
2828
Emeric Brunef42d922012-10-11 16:11:36 +02002829/* parse the "ca-file" server keyword */
2830static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2831{
2832 if (!*args[*cur_arg + 1]) {
2833 if (err)
2834 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
2835 return ERR_ALERT | ERR_FATAL;
2836 }
2837
2838 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2839 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2840 else
2841 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
2842
2843 return 0;
2844}
2845
Willy Tarreau92faadf2012-10-10 23:04:25 +02002846/* parse the "check-ssl" server keyword */
2847static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2848{
2849 newsrv->check.use_ssl = 1;
2850 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2851 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2852 return 0;
2853}
2854
2855/* parse the "ciphers" server keyword */
2856static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2857{
2858 if (!*args[*cur_arg + 1]) {
2859 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
2860 return ERR_ALERT | ERR_FATAL;
2861 }
2862
2863 free(newsrv->ssl_ctx.ciphers);
2864 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
2865 return 0;
2866}
2867
Emeric Brunef42d922012-10-11 16:11:36 +02002868/* parse the "crl-file" server keyword */
2869static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2870{
2871#ifndef X509_V_FLAG_CRL_CHECK
2872 if (err)
2873 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
2874 return ERR_ALERT | ERR_FATAL;
2875#else
2876 if (!*args[*cur_arg + 1]) {
2877 if (err)
2878 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
2879 return ERR_ALERT | ERR_FATAL;
2880 }
2881
2882 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2883 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2884 else
2885 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
2886
2887 return 0;
2888#endif
2889}
2890
Emeric Bruna7aa3092012-10-26 12:58:00 +02002891/* parse the "crt" server keyword */
2892static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2893{
2894 if (!*args[*cur_arg + 1]) {
2895 if (err)
2896 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
2897 return ERR_ALERT | ERR_FATAL;
2898 }
2899
2900 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
2901 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2902 else
2903 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
2904
2905 return 0;
2906}
Emeric Brunef42d922012-10-11 16:11:36 +02002907
Willy Tarreau92faadf2012-10-10 23:04:25 +02002908/* parse the "force-sslv3" server keyword */
2909static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2910{
2911 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
2912 return 0;
2913}
2914
2915/* parse the "force-tlsv10" server keyword */
2916static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2917{
2918 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
2919 return 0;
2920}
2921
2922/* parse the "force-tlsv11" server keyword */
2923static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2924{
2925#if SSL_OP_NO_TLSv1_1
2926 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
2927 return 0;
2928#else
2929 if (err)
2930 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
2931 return ERR_ALERT | ERR_FATAL;
2932#endif
2933}
2934
2935/* parse the "force-tlsv12" server keyword */
2936static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2937{
2938#if SSL_OP_NO_TLSv1_2
2939 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
2940 return 0;
2941#else
2942 if (err)
2943 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
2944 return ERR_ALERT | ERR_FATAL;
2945#endif
2946}
2947
2948/* parse the "no-sslv3" server keyword */
2949static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2950{
2951 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
2952 return 0;
2953}
2954
2955/* parse the "no-tlsv10" server keyword */
2956static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2957{
2958 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
2959 return 0;
2960}
2961
2962/* parse the "no-tlsv11" server keyword */
2963static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2964{
2965 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
2966 return 0;
2967}
2968
2969/* parse the "no-tlsv12" server keyword */
2970static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2971{
2972 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
2973 return 0;
2974}
2975
Emeric Brunf9c5c472012-10-11 15:28:34 +02002976/* parse the "no-tls-tickets" server keyword */
2977static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2978{
2979 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
2980 return 0;
2981}
2982
Willy Tarreau92faadf2012-10-10 23:04:25 +02002983/* parse the "ssl" server keyword */
2984static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2985{
2986 newsrv->use_ssl = 1;
2987 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2988 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2989 return 0;
2990}
2991
Emeric Brunef42d922012-10-11 16:11:36 +02002992/* parse the "verify" server keyword */
2993static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2994{
2995 if (!*args[*cur_arg + 1]) {
2996 if (err)
2997 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
2998 return ERR_ALERT | ERR_FATAL;
2999 }
3000
3001 if (strcmp(args[*cur_arg + 1], "none") == 0)
3002 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
3003 else if (strcmp(args[*cur_arg + 1], "required") == 0)
3004 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
3005 else {
3006 if (err)
3007 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
3008 args[*cur_arg], args[*cur_arg + 1]);
3009 return ERR_ALERT | ERR_FATAL;
3010 }
3011
3012 return 0;
3013}
3014
Willy Tarreau7875d092012-09-10 08:20:03 +02003015/* Note: must not be declared <const> as its list will be overwritten.
3016 * Please take care of keeping this list alphabetically sorted.
3017 */
3018static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
Willy Tarreau80aca902013-01-07 15:42:20 +01003019 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3020 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3021 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3022 { "ssl_c_i_dn", smp_fetch_ssl_c_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3023 { "ssl_c_key_alg", smp_fetch_ssl_c_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3024 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3025 { "ssl_c_notbefore", smp_fetch_ssl_c_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3026 { "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3027 { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3028 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3029 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3030 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3031 { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3032 { "ssl_f_i_dn", smp_fetch_ssl_f_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3033 { "ssl_f_key_alg", smp_fetch_ssl_f_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3034 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3035 { "ssl_f_notbefore", smp_fetch_ssl_f_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3036 { "ssl_f_sig_alg", smp_fetch_ssl_f_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3037 { "ssl_f_s_dn", smp_fetch_ssl_f_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3038 { "ssl_f_serial", smp_fetch_ssl_f_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3039 { "ssl_f_version", smp_fetch_ssl_f_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3040 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3041 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3042 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3043 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3044 { "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 +02003045#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau80aca902013-01-07 15:42:20 +01003046 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003047#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003048#ifdef OPENSSL_ALPN_NEGOTIATED
3049 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3050#endif
Willy Tarreau80aca902013-01-07 15:42:20 +01003051 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3052 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3053 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_CBIN, SMP_USE_L5CLI },
3054 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreau7875d092012-09-10 08:20:03 +02003055 { NULL, NULL, 0, 0, 0 },
3056}};
3057
3058/* Note: must not be declared <const> as its list will be overwritten.
3059 * Please take care of keeping this list alphabetically sorted.
3060 */
3061static struct acl_kw_list acl_kws = {{ },{
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003062 { "ssl_c_ca_err", NULL, acl_parse_int, acl_match_int },
3063 { "ssl_c_ca_err_depth", NULL, acl_parse_int, acl_match_int },
3064 { "ssl_c_err", NULL, acl_parse_int, acl_match_int },
3065 { "ssl_c_i_dn", NULL, acl_parse_str, acl_match_str },
3066 { "ssl_c_key_alg", NULL, acl_parse_str, acl_match_str },
3067 { "ssl_c_notafter", NULL, acl_parse_str, acl_match_str },
3068 { "ssl_c_notbefore", NULL, acl_parse_str, acl_match_str },
3069 { "ssl_c_sig_alg", NULL, acl_parse_str, acl_match_str },
3070 { "ssl_c_s_dn", NULL, acl_parse_str, acl_match_str },
3071 { "ssl_c_serial", NULL, acl_parse_bin, acl_match_bin },
3072 { "ssl_c_used", NULL, acl_parse_nothing, acl_match_nothing },
3073 { "ssl_c_verify", NULL, acl_parse_int, acl_match_int },
3074 { "ssl_c_version", NULL, acl_parse_int, acl_match_int },
3075 { "ssl_f_i_dn", NULL, acl_parse_str, acl_match_str },
3076 { "ssl_f_key_alg", NULL, acl_parse_str, acl_match_str },
3077 { "ssl_f_notafter", NULL, acl_parse_str, acl_match_str },
3078 { "ssl_f_notbefore", NULL, acl_parse_str, acl_match_str },
3079 { "ssl_f_sig_alg", NULL, acl_parse_str, acl_match_str },
3080 { "ssl_f_s_dn", NULL, acl_parse_str, acl_match_str },
3081 { "ssl_f_serial", NULL, acl_parse_bin, acl_match_bin },
3082 { "ssl_f_version", NULL, acl_parse_int, acl_match_int },
3083 { "ssl_fc", NULL, acl_parse_nothing, acl_match_nothing },
3084 { "ssl_fc_alg_keysize", NULL, acl_parse_int, acl_match_int },
3085 { "ssl_fc_cipher", NULL, acl_parse_str, acl_match_str },
3086 { "ssl_fc_has_crt", NULL, acl_parse_nothing, acl_match_nothing },
3087 { "ssl_fc_has_sni", NULL, acl_parse_nothing, acl_match_nothing },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003088#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003089 { "ssl_fc_npn", NULL, acl_parse_str, acl_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003090#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003091#ifdef OPENSSL_ALPN_NEGOTIATED
3092 { "ssl_fc_alpn", NULL, acl_parse_str, acl_match_str },
3093#endif
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003094 { "ssl_fc_protocol", NULL, acl_parse_str, acl_match_str },
3095 { "ssl_fc_use_keysize", NULL, acl_parse_int, acl_match_int },
3096 { "ssl_fc_sni", "ssl_fc_sni", acl_parse_str, acl_match_str },
3097 { "ssl_fc_sni_end", "ssl_fc_sni", acl_parse_str, acl_match_end },
3098 { "ssl_fc_sni_reg", "ssl_fc_sni", acl_parse_reg, acl_match_reg },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01003099 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02003100}};
3101
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003102/* Note: must not be declared <const> as its list will be overwritten.
3103 * Please take care of keeping this list alphabetically sorted, doing so helps
3104 * all code contributors.
3105 * Optional keywords are also declared with a NULL ->parse() function so that
3106 * the config parser can report an appropriate error when a known keyword was
3107 * not enabled.
3108 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02003109static struct bind_kw_list bind_kws = { "SSL", { }, {
Willy Tarreauab861d32013-04-02 02:30:41 +02003110 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003111 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003112 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
3113 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003114 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003115 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
3116 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003117 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003118 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003119 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
3120 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
3121 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
3122 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02003123 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
3124 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
3125 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
3126 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003127 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003128 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003129 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003130 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003131 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003132 { NULL, NULL, 0 },
3133}};
Emeric Brun46591952012-05-18 15:47:34 +02003134
Willy Tarreau92faadf2012-10-10 23:04:25 +02003135/* Note: must not be declared <const> as its list will be overwritten.
3136 * Please take care of keeping this list alphabetically sorted, doing so helps
3137 * all code contributors.
3138 * Optional keywords are also declared with a NULL ->parse() function so that
3139 * the config parser can report an appropriate error when a known keyword was
3140 * not enabled.
3141 */
3142static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02003143 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003144 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
3145 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02003146 { "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 +02003147 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003148 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
3149 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
3150 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
3151 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
3152 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
3153 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
3154 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
3155 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02003156 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003157 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02003158 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Willy Tarreau92faadf2012-10-10 23:04:25 +02003159 { NULL, NULL, 0, 0 },
3160}};
3161
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003162/* transport-layer operations for SSL sockets */
3163struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02003164 .snd_buf = ssl_sock_from_buf,
3165 .rcv_buf = ssl_sock_to_buf,
3166 .rcv_pipe = NULL,
3167 .snd_pipe = NULL,
3168 .shutr = NULL,
3169 .shutw = ssl_sock_shutw,
3170 .close = ssl_sock_close,
3171 .init = ssl_sock_init,
3172};
3173
3174__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02003175static void __ssl_sock_init(void)
3176{
Emeric Brun46591952012-05-18 15:47:34 +02003177 STACK_OF(SSL_COMP)* cm;
3178
3179 SSL_library_init();
3180 cm = SSL_COMP_get_compression_methods();
3181 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02003182 sample_register_fetches(&sample_fetch_keywords);
3183 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003184 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02003185 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02003186}
3187
3188/*
3189 * Local variables:
3190 * c-indent-level: 8
3191 * c-basic-offset: 8
3192 * End:
3193 */