blob: 34f24b56dc6fb8f26250d26e096ecdeb6dd84285 [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;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200192 struct ebmb_node *node, *n;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200193 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) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200198 return (s->strict_sni ?
199 SSL_TLSEXT_ERR_ALERT_FATAL :
200 SSL_TLSEXT_ERR_ALERT_WARNING);
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100201 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200202
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100203 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200204 if (!servername[i])
205 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100206 trash.str[i] = tolower(servername[i]);
207 if (!wildp && (trash.str[i] == '.'))
208 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200209 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100210 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200211
212 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100213 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200214
215 /* lookup a not neg filter */
216 for (n = node; n; n = ebmb_next_dup(n)) {
217 if (!container_of(n, struct sni_ctx, name)->neg) {
218 node = n;
219 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100220 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200221 wildp = NULL; /* never match a wildcard after matching a neg */
222 }
223 if (!node && wildp) {
224 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +0200225 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200226 }
227 if (!node || container_of(node, struct sni_ctx, name)->neg) {
228 return (s->strict_sni ?
229 SSL_TLSEXT_ERR_ALERT_FATAL :
230 SSL_TLSEXT_ERR_ALERT_WARNING);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200231 }
232
233 /* switch ctx */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200234 SSL_set_SSL_CTX(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200235 return SSL_TLSEXT_ERR_OK;
236}
237#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
238
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200239#ifndef OPENSSL_NO_DH
240/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
241 if an error occured, and 0 if parameter not found. */
242int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
243{
244 int ret = -1;
245 BIO *in;
246 DH *dh = NULL;
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200247 /* If not present, use parameters generated using 'openssl dhparam 1024 -C':
248 * -----BEGIN DH PARAMETERS-----
249 * MIGHAoGBAJJAJDXDoS5E03MNjnjK36eOL1tRqVa/9NuOVlI+lpXmPjJQbP65EvKn
250 * fSLnG7VMhoCJO4KtG88zf393ltP7loGB2bofcDSr+x+XsxBM8yA/Zj6BmQt+CQ9s
251 * TF7hoOV+wXTT6ErZ5y5qx9pq6hLfKXwTGFT78hrE6HnCO7xgtPdTAgEC
252 * -----END DH PARAMETERS-----
253 */
254 static const unsigned char dh1024_p[] = {
255 0x92, 0x40, 0x24, 0x35, 0xC3, 0xA1, 0x2E, 0x44, 0xD3, 0x73, 0x0D, 0x8E,
256 0x78, 0xCA, 0xDF, 0xA7, 0x8E, 0x2F, 0x5B, 0x51, 0xA9, 0x56, 0xBF, 0xF4,
257 0xDB, 0x8E, 0x56, 0x52, 0x3E, 0x96, 0x95, 0xE6, 0x3E, 0x32, 0x50, 0x6C,
258 0xFE, 0xB9, 0x12, 0xF2, 0xA7, 0x7D, 0x22, 0xE7, 0x1B, 0xB5, 0x4C, 0x86,
259 0x80, 0x89, 0x3B, 0x82, 0xAD, 0x1B, 0xCF, 0x33, 0x7F, 0x7F, 0x77, 0x96,
260 0xD3, 0xFB, 0x96, 0x81, 0x81, 0xD9, 0xBA, 0x1F, 0x70, 0x34, 0xAB, 0xFB,
261 0x1F, 0x97, 0xB3, 0x10, 0x4C, 0xF3, 0x20, 0x3F, 0x66, 0x3E, 0x81, 0x99,
262 0x0B, 0x7E, 0x09, 0x0F, 0x6C, 0x4C, 0x5E, 0xE1, 0xA0, 0xE5, 0x7E, 0xC1,
263 0x74, 0xD3, 0xE8, 0x4A, 0xD9, 0xE7, 0x2E, 0x6A, 0xC7, 0xDA, 0x6A, 0xEA,
264 0x12, 0xDF, 0x29, 0x7C, 0x13, 0x18, 0x54, 0xFB, 0xF2, 0x1A, 0xC4, 0xE8,
265 0x79, 0xC2, 0x3B, 0xBC, 0x60, 0xB4, 0xF7, 0x53,
266 };
267 static const unsigned char dh1024_g[] = {
268 0x02,
269 };
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200270
271 in = BIO_new(BIO_s_file());
272 if (in == NULL)
273 goto end;
274
275 if (BIO_read_filename(in, file) <= 0)
276 goto end;
277
278 dh = PEM_read_bio_DHparams(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200279 if (!dh) {
280 /* Clear openssl global errors stack */
281 ERR_clear_error();
282
283 dh = DH_new();
284 if (dh == NULL)
285 goto end;
286
287 dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
288 if (dh->p == NULL)
289 goto end;
290
291 dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
292 if (dh->g == NULL)
293 goto end;
294
295 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200296 }
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200297 else
298 ret = 1;
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200299
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200300 SSL_CTX_set_tmp_dh(ctx, dh);
Emeric Brun644cde02012-12-14 11:21:13 +0100301
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200302end:
303 if (dh)
304 DH_free(dh);
305
306 if (in)
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200307 BIO_free(in);
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200308
309 return ret;
310}
311#endif
312
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200313static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100314{
315 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200316 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100317
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200318 if (*name == '!') {
319 neg = 1;
320 name++;
321 }
322 if (*name == '*') {
323 wild = 1;
324 name++;
325 }
326 /* !* filter is a nop */
327 if (neg && wild)
328 return order;
329 if (*name) {
330 int j, len;
331 len = strlen(name);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100332 sc = malloc(sizeof(struct sni_ctx) + len + 1);
333 for (j = 0; j < len; j++)
334 sc->name.key[j] = tolower(name[j]);
335 sc->name.key[len] = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100336 sc->ctx = ctx;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200337 sc->order = order++;
338 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100339 if (wild)
340 ebst_insert(&s->sni_w_ctx, &sc->name);
341 else
342 ebst_insert(&s->sni_ctx, &sc->name);
343 }
344 return order;
345}
346
Emeric Brunfc0421f2012-09-07 17:30:07 +0200347/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
348 * an early error happens and the caller must call SSL_CTX_free() by itelf.
349 */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200350static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200351{
352 BIO *in;
353 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200354 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200355 int ret = -1;
356 int order = 0;
357 X509_NAME *xname;
358 char *str;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200359#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
360 STACK_OF(GENERAL_NAME) *names;
361#endif
362
363 in = BIO_new(BIO_s_file());
364 if (in == NULL)
365 goto end;
366
367 if (BIO_read_filename(in, file) <= 0)
368 goto end;
369
370 x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
371 if (x == NULL)
372 goto end;
373
Emeric Brun50bcecc2013-04-22 13:05:23 +0200374 if (fcount) {
375 while (fcount--)
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200376 order = ssl_sock_add_cert_sni(ctx, s, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100377 }
378 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200379#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100380 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
381 if (names) {
382 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
383 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
384 if (name->type == GEN_DNS) {
385 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200386 order = ssl_sock_add_cert_sni(ctx, s, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100387 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200388 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200389 }
390 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100391 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200392 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200393#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100394 xname = X509_get_subject_name(x);
395 i = -1;
396 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
397 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
398 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200399 order = ssl_sock_add_cert_sni(ctx, s, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100400 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200401 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200402 }
403 }
404
405 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
406 if (!SSL_CTX_use_certificate(ctx, x))
407 goto end;
408
409 if (ctx->extra_certs != NULL) {
410 sk_X509_pop_free(ctx->extra_certs, X509_free);
411 ctx->extra_certs = NULL;
412 }
413
414 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata))) {
415 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
416 X509_free(ca);
417 goto end;
418 }
419 }
420
421 err = ERR_get_error();
422 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
423 /* we successfully reached the last cert in the file */
424 ret = 1;
425 }
426 ERR_clear_error();
427
428end:
429 if (x)
430 X509_free(x);
431
432 if (in)
433 BIO_free(in);
434
435 return ret;
436}
437
Emeric Brun50bcecc2013-04-22 13:05:23 +0200438static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200439{
440 int ret;
441 SSL_CTX *ctx;
442
443 ctx = SSL_CTX_new(SSLv23_server_method());
444 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200445 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
446 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200447 return 1;
448 }
449
450 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200451 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
452 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200453 SSL_CTX_free(ctx);
454 return 1;
455 }
456
Emeric Brun50bcecc2013-04-22 13:05:23 +0200457 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200458 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200459 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
460 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200461 if (ret < 0) /* serious error, must do that ourselves */
462 SSL_CTX_free(ctx);
463 return 1;
464 }
Emeric Brun61694ab2012-10-26 13:35:33 +0200465
466 if (SSL_CTX_check_private_key(ctx) <= 0) {
467 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
468 err && *err ? *err : "", path);
469 return 1;
470 }
471
Emeric Brunfc0421f2012-09-07 17:30:07 +0200472 /* we must not free the SSL_CTX anymore below, since it's already in
473 * the tree, so it will be discovered and cleaned in time.
474 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200475#ifndef OPENSSL_NO_DH
476 ret = ssl_sock_load_dh_params(ctx, path);
477 if (ret < 0) {
478 if (err)
479 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
480 *err ? *err : "", path);
481 return 1;
482 }
483#endif
484
Emeric Brunfc0421f2012-09-07 17:30:07 +0200485#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200486 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200487 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
488 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +0200489 return 1;
490 }
491#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200492 if (!bind_conf->default_ctx)
493 bind_conf->default_ctx = ctx;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200494
495 return 0;
496}
497
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200498int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200499{
500 struct dirent *de;
501 DIR *dir;
502 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +0100503 char *end;
504 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200505 int cfgerr = 0;
506
507 if (!(dir = opendir(path)))
Emeric Brun50bcecc2013-04-22 13:05:23 +0200508 return ssl_sock_load_cert_file(path, bind_conf, curproxy, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200509
510 /* strip trailing slashes, including first one */
511 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
512 *end = 0;
513
Emeric Brunfc0421f2012-09-07 17:30:07 +0200514 while ((de = readdir(dir))) {
Willy Tarreauee2663b2012-12-06 11:36:59 +0100515 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200516 if (stat(fp, &buf) != 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200517 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
518 err && *err ? *err : "", fp, strerror(errno));
Emeric Brunfc0421f2012-09-07 17:30:07 +0200519 cfgerr++;
520 continue;
521 }
522 if (!S_ISREG(buf.st_mode))
523 continue;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200524 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, curproxy, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200525 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200526 closedir(dir);
527 return cfgerr;
528}
529
Thierry Fournier383085f2013-01-24 14:15:43 +0100530/* Make sure openssl opens /dev/urandom before the chroot. The work is only
531 * done once. Zero is returned if the operation fails. No error is returned
532 * if the random is said as not implemented, because we expect that openssl
533 * will use another method once needed.
534 */
535static int ssl_initialize_random()
536{
537 unsigned char random;
538 static int random_initialized = 0;
539
540 if (!random_initialized && RAND_bytes(&random, 1) != 0)
541 random_initialized = 1;
542
543 return random_initialized;
544}
545
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100546int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
547{
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200548 char thisline[LINESIZE];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100549 FILE *f;
550 int linenum = 0;
551 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100552
Willy Tarreauad1731d2013-04-02 17:35:58 +0200553 if ((f = fopen(file, "r")) == NULL) {
554 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100555 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200556 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100557
558 while (fgets(thisline, sizeof(thisline), f) != NULL) {
559 int arg;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200560 int newarg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100561 char *end;
562 char *args[MAX_LINE_ARGS + 1];
563 char *line = thisline;
564
565 linenum++;
566 end = line + strlen(line);
567 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
568 /* Check if we reached the limit and the last char is not \n.
569 * Watch out for the last line without the terminating '\n'!
570 */
Willy Tarreauad1731d2013-04-02 17:35:58 +0200571 memprintf(err, "line %d too long in file '%s', limit is %d characters",
572 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100573 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200574 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100575 }
576
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100577 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200578 newarg = 1;
579 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100580 if (*line == '#' || *line == '\n' || *line == '\r') {
581 /* end of string, end of loop */
582 *line = 0;
583 break;
584 }
585 else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +0200586 newarg = 1;
587 *line = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100588 }
Emeric Brun50bcecc2013-04-22 13:05:23 +0200589 else if (newarg) {
590 if (arg == MAX_LINE_ARGS) {
591 memprintf(err, "too many args on line %d in file '%s'.",
592 linenum, file);
593 cfgerr = 1;
594 break;
595 }
596 newarg = 0;
597 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100598 }
Emeric Brun50bcecc2013-04-22 13:05:23 +0200599 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100600 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200601 if (cfgerr)
602 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200603
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100604 /* empty line */
Emeric Brun50bcecc2013-04-22 13:05:23 +0200605 if (!arg)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100606 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100607
Emeric Brun50bcecc2013-04-22 13:05:23 +0200608 cfgerr = ssl_sock_load_cert_file(args[0], bind_conf, curproxy, &args[1], arg-1, err);
Willy Tarreauad1731d2013-04-02 17:35:58 +0200609 if (cfgerr) {
610 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100611 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200612 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100613 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100614 fclose(f);
615 return cfgerr;
616}
617
Emeric Brunfc0421f2012-09-07 17:30:07 +0200618#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
619#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
620#endif
621
622#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
623#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
Willy Tarreau7d588ee2012-11-26 18:47:31 +0100624#define SSL_renegotiate_pending(arg) 0
Emeric Brunfc0421f2012-09-07 17:30:07 +0200625#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200626#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
627#define SSL_OP_SINGLE_ECDH_USE 0
628#endif
Emeric Brun2d0c4822012-10-02 13:45:20 +0200629#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
630#define SSL_OP_NO_TICKET 0
631#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200632#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
633#define SSL_OP_NO_COMPRESSION 0
634#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +0200635#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
636#define SSL_OP_NO_TLSv1_1 0
637#endif
638#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
639#define SSL_OP_NO_TLSv1_2 0
640#endif
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200641#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
642#define SSL_OP_SINGLE_DH_USE 0
643#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200644#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
645#define SSL_OP_SINGLE_ECDH_USE 0
646#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200647#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
648#define SSL_MODE_RELEASE_BUFFERS 0
649#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200650int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy *curproxy)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200651{
652 int cfgerr = 0;
653 int ssloptions =
654 SSL_OP_ALL | /* all known workarounds for bugs */
655 SSL_OP_NO_SSLv2 |
656 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200657 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +0200658 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +0200659 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
660 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200661 int sslmode =
662 SSL_MODE_ENABLE_PARTIAL_WRITE |
663 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
664 SSL_MODE_RELEASE_BUFFERS;
665
Thierry Fournier383085f2013-01-24 14:15:43 +0100666 /* Make sure openssl opens /dev/urandom before the chroot */
667 if (!ssl_initialize_random()) {
668 Alert("OpenSSL random data generator initialization failed.\n");
669 cfgerr++;
670 }
671
Emeric Brun89675492012-10-05 13:48:26 +0200672 if (bind_conf->ssl_options & BC_SSL_O_NO_SSLV3)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200673 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brun89675492012-10-05 13:48:26 +0200674 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV10)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200675 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun89675492012-10-05 13:48:26 +0200676 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV11)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200677 ssloptions |= SSL_OP_NO_TLSv1_1;
Emeric Brun89675492012-10-05 13:48:26 +0200678 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV12)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200679 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun89675492012-10-05 13:48:26 +0200680 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
Emeric Brun2d0c4822012-10-02 13:45:20 +0200681 ssloptions |= SSL_OP_NO_TICKET;
Emeric Brun2cb7ae52012-10-05 14:14:21 +0200682 if (bind_conf->ssl_options & BC_SSL_O_USE_SSLV3)
683 SSL_CTX_set_ssl_version(ctx, SSLv3_server_method());
684 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV10)
685 SSL_CTX_set_ssl_version(ctx, TLSv1_server_method());
686#if SSL_OP_NO_TLSv1_1
687 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV11)
688 SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method());
689#endif
690#if SSL_OP_NO_TLSv1_2
691 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV12)
692 SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method());
693#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200694
695 SSL_CTX_set_options(ctx, ssloptions);
696 SSL_CTX_set_mode(ctx, sslmode);
Emeric Brune64aef12012-09-21 13:15:06 +0200697 SSL_CTX_set_verify(ctx, bind_conf->verify ? bind_conf->verify : SSL_VERIFY_NONE, ssl_sock_verifycbk);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200698 if (bind_conf->verify & SSL_VERIFY_PEER) {
Emeric Brunfb510ea2012-10-05 12:00:26 +0200699 if (bind_conf->ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200700 /* load CAfile to verify */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200701 if (!SSL_CTX_load_verify_locations(ctx, bind_conf->ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200702 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200703 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200704 cfgerr++;
705 }
706 /* set CA names fo client cert request, function returns void */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200707 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(bind_conf->ca_file));
Emeric Brund94b3fe2012-09-20 18:23:56 +0200708 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200709#ifdef X509_V_FLAG_CRL_CHECK
Emeric Brunfb510ea2012-10-05 12:00:26 +0200710 if (bind_conf->crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200711 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
712
Emeric Brunfb510ea2012-10-05 12:00:26 +0200713 if (!store || !X509_STORE_load_locations(store, bind_conf->crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200714 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200715 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200716 cfgerr++;
717 }
Emeric Brun561e5742012-10-02 15:20:55 +0200718 else {
719 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
720 }
Emeric Brund94b3fe2012-09-20 18:23:56 +0200721 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200722#endif
Emeric Brun644cde02012-12-14 11:21:13 +0100723 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +0200724 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200725
Emeric Brun4f65bff2012-11-16 15:11:00 +0100726 if (global.tune.ssllifetime)
727 SSL_CTX_set_timeout(ctx, global.tune.ssllifetime);
728
Emeric Brunfc0421f2012-09-07 17:30:07 +0200729 shared_context_set_cache(ctx);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200730 if (bind_conf->ciphers &&
731 !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200732 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 +0200733 curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200734 cfgerr++;
735 }
736
737 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200738#ifdef OPENSSL_NPN_NEGOTIATED
739 if (bind_conf->npn_str)
740 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
741#endif
Willy Tarreauab861d32013-04-02 02:30:41 +0200742#ifdef OPENSSL_ALPN_NEGOTIATED
743 if (bind_conf->alpn_str)
744 SSL_CTX_set_alpn_advertised_cb(ctx, ssl_sock_advertise_alpn_protos, bind_conf);
745#endif
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200746
Emeric Brunfc0421f2012-09-07 17:30:07 +0200747#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
748 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200749 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200750#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200751#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emeric Brun6924ef82013-03-06 14:08:53 +0100752 {
Emeric Brun2b58d042012-09-20 17:10:03 +0200753 int i;
754 EC_KEY *ecdh;
755
Emeric Brun6924ef82013-03-06 14:08:53 +0100756 i = OBJ_sn2nid(bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE);
Emeric Brun2b58d042012-09-20 17:10:03 +0200757 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
758 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 +0100759 curproxy->id, bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE,
760 bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +0200761 cfgerr++;
762 }
763 else {
764 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
765 EC_KEY_free(ecdh);
766 }
767 }
768#endif
769
Emeric Brunfc0421f2012-09-07 17:30:07 +0200770 return cfgerr;
771}
772
Emeric Brun94324a42012-10-11 14:00:19 +0200773/* prepare ssl context from servers options. Returns an error count */
774int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
775{
776 int cfgerr = 0;
777 int options =
778 SSL_OP_ALL | /* all known workarounds for bugs */
779 SSL_OP_NO_SSLv2 |
780 SSL_OP_NO_COMPRESSION;
781 int mode =
782 SSL_MODE_ENABLE_PARTIAL_WRITE |
783 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
784 SSL_MODE_RELEASE_BUFFERS;
785
Thierry Fournier383085f2013-01-24 14:15:43 +0100786 /* Make sure openssl opens /dev/urandom before the chroot */
787 if (!ssl_initialize_random()) {
788 Alert("OpenSSL random data generator initialization failed.\n");
789 cfgerr++;
790 }
791
Emeric Brun94324a42012-10-11 14:00:19 +0200792 /* Initiate SSL context for current server */
793 srv->ssl_ctx.reused_sess = NULL;
794 if (srv->use_ssl)
795 srv->xprt = &ssl_sock;
796 if (srv->check.use_ssl)
797 srv->check.xprt = &ssl_sock;
798
799 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
800 if (!srv->ssl_ctx.ctx) {
801 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
802 proxy_type_str(curproxy), curproxy->id,
803 srv->id);
804 cfgerr++;
805 return cfgerr;
806 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200807 if (srv->ssl_ctx.client_crt) {
808 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
809 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
810 proxy_type_str(curproxy), curproxy->id,
811 srv->id, srv->ssl_ctx.client_crt);
812 cfgerr++;
813 }
814 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
815 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
816 proxy_type_str(curproxy), curproxy->id,
817 srv->id, srv->ssl_ctx.client_crt);
818 cfgerr++;
819 }
820 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
821 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
822 proxy_type_str(curproxy), curproxy->id,
823 srv->id, srv->ssl_ctx.client_crt);
824 cfgerr++;
825 }
826 }
Emeric Brun94324a42012-10-11 14:00:19 +0200827
828 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
829 options |= SSL_OP_NO_SSLv3;
830 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
831 options |= SSL_OP_NO_TLSv1;
832 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
833 options |= SSL_OP_NO_TLSv1_1;
834 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
835 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200836 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
837 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200838 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
839 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
840 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
841 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
842#if SSL_OP_NO_TLSv1_1
843 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
844 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
845#endif
846#if SSL_OP_NO_TLSv1_2
847 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
848 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
849#endif
850
851 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
852 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Emeric Brunef42d922012-10-11 16:11:36 +0200853 SSL_CTX_set_verify(srv->ssl_ctx.ctx, srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE, NULL);
854 if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
855 if (srv->ssl_ctx.ca_file) {
856 /* load CAfile to verify */
857 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
858 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
859 curproxy->id, srv->id,
860 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
861 cfgerr++;
862 }
863 }
864#ifdef X509_V_FLAG_CRL_CHECK
865 if (srv->ssl_ctx.crl_file) {
866 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
867
868 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
869 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
870 curproxy->id, srv->id,
871 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
872 cfgerr++;
873 }
874 else {
875 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
876 }
877 }
878#endif
879 }
880
Emeric Brun4f65bff2012-11-16 15:11:00 +0100881 if (global.tune.ssllifetime)
882 SSL_CTX_set_timeout(srv->ssl_ctx.ctx, global.tune.ssllifetime);
883
Emeric Brun94324a42012-10-11 14:00:19 +0200884 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
885 if (srv->ssl_ctx.ciphers &&
886 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
887 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
888 curproxy->id, srv->id,
889 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
890 cfgerr++;
891 }
892
893 return cfgerr;
894}
895
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200896/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200897 * be NULL, in which case nothing is done. Returns the number of errors
898 * encountered.
899 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200900int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200901{
902 struct ebmb_node *node;
903 struct sni_ctx *sni;
904 int err = 0;
905
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200906 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200907 return 0;
908
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200909 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200910 while (node) {
911 sni = ebmb_entry(node, struct sni_ctx, name);
912 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200913 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200914 node = ebmb_next(node);
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 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200921 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200922 node = ebmb_next(node);
923 }
924 return err;
925}
926
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200927/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200928 * be NULL, in which case nothing is done. The default_ctx is nullified too.
929 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200930void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200931{
932 struct ebmb_node *node, *back;
933 struct sni_ctx *sni;
934
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200935 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200936 return;
937
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200938 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200939 while (node) {
940 sni = ebmb_entry(node, struct sni_ctx, name);
941 back = ebmb_next(node);
942 ebmb_delete(node);
943 if (!sni->order) /* only free the CTX on its first occurrence */
944 SSL_CTX_free(sni->ctx);
945 free(sni);
946 node = back;
947 }
948
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200949 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200950 while (node) {
951 sni = ebmb_entry(node, struct sni_ctx, name);
952 back = ebmb_next(node);
953 ebmb_delete(node);
954 if (!sni->order) /* only free the CTX on its first occurrence */
955 SSL_CTX_free(sni->ctx);
956 free(sni);
957 node = back;
958 }
959
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200960 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +0200961}
962
Emeric Brun46591952012-05-18 15:47:34 +0200963/*
964 * This function is called if SSL * context is not yet allocated. The function
965 * is designed to be called before any other data-layer operation and sets the
966 * handshake flag on the connection. It is safe to call it multiple times.
967 * It returns 0 on success and -1 in error case.
968 */
969static int ssl_sock_init(struct connection *conn)
970{
971 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200972 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200973 return 0;
974
Willy Tarreau20879a02012-12-03 16:32:10 +0100975 if (global.maxsslconn && sslconns >= global.maxsslconn) {
976 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +0200977 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100978 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200979
Emeric Brun46591952012-05-18 15:47:34 +0200980 /* If it is in client mode initiate SSL session
981 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100982 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200983 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100984 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +0100985 if (!conn->xprt_ctx) {
986 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +0200987 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100988 }
Emeric Brun46591952012-05-18 15:47:34 +0200989
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200990 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100991 if (objt_server(conn->target)->ssl_ctx.reused_sess)
992 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +0200993
994 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200995 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200996
997 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200998 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200999
1000 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001001 return 0;
1002 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001003 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001004 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001005 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001006 if (!conn->xprt_ctx) {
1007 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001008 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001009 }
Emeric Brun46591952012-05-18 15:47:34 +02001010
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001011 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001012
1013 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001014 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001015
Emeric Brune1f38db2012-09-03 20:36:47 +02001016 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001017 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +02001018
Emeric Brun46591952012-05-18 15:47:34 +02001019 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001020 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001021
1022 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001023 return 0;
1024 }
1025 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01001026 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02001027 return -1;
1028}
1029
1030
1031/* This is the callback which is used when an SSL handshake is pending. It
1032 * updates the FD status if it wants some polling before being called again.
1033 * It returns 0 if it fails in a fatal way or needs to poll to go further,
1034 * otherwise it returns non-zero and removes itself from the connection's
1035 * flags (the bit is provided in <flag> by the caller).
1036 */
1037int ssl_sock_handshake(struct connection *conn, unsigned int flag)
1038{
1039 int ret;
1040
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001041 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001042 goto out_error;
1043
Emeric Brun674b7432012-11-08 19:21:55 +01001044 /* If we use SSL_do_handshake to process a reneg initiated by
1045 * the remote peer, it sometimes returns SSL_ERROR_SSL.
1046 * Usually SSL_write and SSL_read are used and process implicitly
1047 * the reneg handshake.
1048 * Here we use SSL_peek as a workaround for reneg.
1049 */
1050 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
1051 char c;
1052
1053 ret = SSL_peek(conn->xprt_ctx, &c, 1);
1054 if (ret <= 0) {
1055 /* handshake may have not been completed, let's find why */
1056 ret = SSL_get_error(conn->xprt_ctx, ret);
1057 if (ret == SSL_ERROR_WANT_WRITE) {
1058 /* SSL handshake needs to write, L4 connection may not be ready */
1059 __conn_sock_stop_recv(conn);
1060 __conn_sock_poll_send(conn);
1061 return 0;
1062 }
1063 else if (ret == SSL_ERROR_WANT_READ) {
1064 /* handshake may have been completed but we have
1065 * no more data to read.
1066 */
1067 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
1068 ret = 1;
1069 goto reneg_ok;
1070 }
1071 /* SSL handshake needs to read, L4 connection is ready */
1072 if (conn->flags & CO_FL_WAIT_L4_CONN)
1073 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1074 __conn_sock_stop_send(conn);
1075 __conn_sock_poll_recv(conn);
1076 return 0;
1077 }
1078 else if (ret == SSL_ERROR_SYSCALL) {
1079 /* if errno is null, then connection was successfully established */
1080 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1081 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001082 if (!conn->err_code) {
1083 if (!((SSL *)conn->xprt_ctx)->packet_length)
1084 if (!errno)
1085 conn->err_code = CO_ER_SSL_EMPTY;
1086 else
1087 conn->err_code = CO_ER_SSL_ABORT;
1088 else
1089 conn->err_code = CO_ER_SSL_HANDSHAKE;
1090 }
Emeric Brun674b7432012-11-08 19:21:55 +01001091 goto out_error;
1092 }
1093 else {
1094 /* Fail on all other handshake errors */
1095 /* Note: OpenSSL may leave unread bytes in the socket's
1096 * buffer, causing an RST to be emitted upon close() on
1097 * TCP sockets. We first try to drain possibly pending
1098 * data to avoid this as much as possible.
1099 */
1100 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Willy Tarreau20879a02012-12-03 16:32:10 +01001101 if (!conn->err_code)
1102 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01001103 goto out_error;
1104 }
1105 }
1106 /* read some data: consider handshake completed */
1107 goto reneg_ok;
1108 }
1109
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001110 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001111 if (ret != 1) {
1112 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001113 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001114
1115 if (ret == SSL_ERROR_WANT_WRITE) {
1116 /* SSL handshake needs to write, L4 connection may not be ready */
1117 __conn_sock_stop_recv(conn);
1118 __conn_sock_poll_send(conn);
1119 return 0;
1120 }
1121 else if (ret == SSL_ERROR_WANT_READ) {
1122 /* SSL handshake needs to read, L4 connection is ready */
1123 if (conn->flags & CO_FL_WAIT_L4_CONN)
1124 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1125 __conn_sock_stop_send(conn);
1126 __conn_sock_poll_recv(conn);
1127 return 0;
1128 }
Willy Tarreau89230192012-09-28 20:22:13 +02001129 else if (ret == SSL_ERROR_SYSCALL) {
1130 /* if errno is null, then connection was successfully established */
1131 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1132 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001133
1134 if (!((SSL *)conn->xprt_ctx)->packet_length)
1135 if (!errno)
1136 conn->err_code = CO_ER_SSL_EMPTY;
1137 else
1138 conn->err_code = CO_ER_SSL_ABORT;
1139 else
1140 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +02001141 goto out_error;
1142 }
Emeric Brun46591952012-05-18 15:47:34 +02001143 else {
1144 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02001145 /* Note: OpenSSL may leave unread bytes in the socket's
1146 * buffer, causing an RST to be emitted upon close() on
1147 * TCP sockets. We first try to drain possibly pending
1148 * data to avoid this as much as possible.
1149 */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01001150 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Willy Tarreau20879a02012-12-03 16:32:10 +01001151 if (!conn->err_code)
1152 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001153 goto out_error;
1154 }
1155 }
1156
Emeric Brun674b7432012-11-08 19:21:55 +01001157reneg_ok:
1158
Emeric Brun46591952012-05-18 15:47:34 +02001159 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001160 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001161 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +02001162 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001163 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1164 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001165
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001166 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001167 }
1168 }
1169
1170 /* The connection is now established at both layers, it's time to leave */
1171 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1172 return 1;
1173
1174 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001175 /* Clear openssl global errors stack */
1176 ERR_clear_error();
1177
Emeric Brun9fa89732012-10-04 17:09:56 +02001178 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001179 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1180 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1181 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001182 }
1183
Emeric Brun46591952012-05-18 15:47:34 +02001184 /* Fail on all other handshake errors */
1185 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001186 if (!conn->err_code)
1187 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001188 return 0;
1189}
1190
1191/* Receive up to <count> bytes from connection <conn>'s socket and store them
1192 * into buffer <buf>. The caller must ensure that <count> is always smaller
1193 * than the buffer's size. Only one call to recv() is performed, unless the
1194 * buffer wraps, in which case a second call may be performed. The connection's
1195 * flags are updated with whatever special event is detected (error, read0,
1196 * empty). The caller is responsible for taking care of those events and
1197 * avoiding the call if inappropriate. The function does not call the
1198 * connection's polling update function, so the caller is responsible for this.
1199 */
1200static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1201{
1202 int ret, done = 0;
1203 int try = count;
1204
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001205 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001206 goto out_error;
1207
1208 if (conn->flags & CO_FL_HANDSHAKE)
1209 /* a handshake was requested */
1210 return 0;
1211
1212 /* compute the maximum block size we can read at once. */
1213 if (buffer_empty(buf)) {
1214 /* let's realign the buffer to optimize I/O */
1215 buf->p = buf->data;
1216 }
1217 else if (buf->data + buf->o < buf->p &&
1218 buf->p + buf->i < buf->data + buf->size) {
1219 /* remaining space wraps at the end, with a moving limit */
1220 if (try > buf->data + buf->size - (buf->p + buf->i))
1221 try = buf->data + buf->size - (buf->p + buf->i);
1222 }
1223
1224 /* read the largest possible block. For this, we perform only one call
1225 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1226 * in which case we accept to do it once again. A new attempt is made on
1227 * EINTR too.
1228 */
1229 while (try) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001230 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001231 if (conn->flags & CO_FL_ERROR) {
1232 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001233 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001234 }
Emeric Brun46591952012-05-18 15:47:34 +02001235 if (ret > 0) {
1236 buf->i += ret;
1237 done += ret;
1238 if (ret < try)
1239 break;
1240 count -= ret;
1241 try = count;
1242 }
1243 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001244 ret = SSL_get_error(conn->xprt_ctx, ret);
1245 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001246 /* error on protocol or underlying transport */
1247 if ((ret != SSL_ERROR_SYSCALL)
1248 || (errno && (errno != EAGAIN)))
1249 conn->flags |= CO_FL_ERROR;
1250
Emeric Brun644cde02012-12-14 11:21:13 +01001251 /* Clear openssl global errors stack */
1252 ERR_clear_error();
1253 }
Emeric Brun46591952012-05-18 15:47:34 +02001254 goto read0;
1255 }
1256 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001257 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001258 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001259 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001260 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001261 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001262 break;
1263 }
1264 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001265 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1266 /* handshake is running, and it may need to re-enable read */
1267 conn->flags |= CO_FL_SSL_WAIT_HS;
1268 __conn_sock_want_recv(conn);
1269 break;
1270 }
Emeric Brun46591952012-05-18 15:47:34 +02001271 /* we need to poll for retry a read later */
1272 __conn_data_poll_recv(conn);
1273 break;
1274 }
1275 /* otherwise it's a real error */
1276 goto out_error;
1277 }
1278 }
1279 return done;
1280
1281 read0:
1282 conn_sock_read0(conn);
1283 return done;
1284 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001285 /* Clear openssl global errors stack */
1286 ERR_clear_error();
1287
Emeric Brun46591952012-05-18 15:47:34 +02001288 conn->flags |= CO_FL_ERROR;
1289 return done;
1290}
1291
1292
1293/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1294 * <flags> may contain MSG_MORE to make the system hold on without sending
1295 * data too fast, but this flag is ignored at the moment.
1296 * Only one call to send() is performed, unless the buffer wraps, in which case
1297 * a second call may be performed. The connection's flags are updated with
1298 * whatever special event is detected (error, empty). The caller is responsible
1299 * for taking care of those events and avoiding the call if inappropriate. The
1300 * function does not call the connection's polling update function, so the caller
1301 * is responsible for this.
1302 */
1303static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1304{
1305 int ret, try, done;
1306
1307 done = 0;
1308
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001309 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001310 goto out_error;
1311
1312 if (conn->flags & CO_FL_HANDSHAKE)
1313 /* a handshake was requested */
1314 return 0;
1315
1316 /* send the largest possible block. For this we perform only one call
1317 * to send() unless the buffer wraps and we exactly fill the first hunk,
1318 * in which case we accept to do it once again.
1319 */
1320 while (buf->o) {
1321 try = buf->o;
Willy Tarreaubfd59462013-02-21 07:46:09 +01001322
1323 if (global.tune.ssl_max_record && try > global.tune.ssl_max_record)
1324 try = global.tune.ssl_max_record;
1325
Emeric Brun46591952012-05-18 15:47:34 +02001326 /* outgoing data may wrap at the end */
1327 if (buf->data + try > buf->p)
1328 try = buf->data + try - buf->p;
1329
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001330 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001331 if (conn->flags & CO_FL_ERROR) {
1332 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001333 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001334 }
Emeric Brun46591952012-05-18 15:47:34 +02001335 if (ret > 0) {
1336 buf->o -= ret;
1337 done += ret;
1338
Willy Tarreau5fb38032012-12-16 19:39:09 +01001339 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001340 /* optimize data alignment in the buffer */
1341 buf->p = buf->data;
1342
1343 /* if the system buffer is full, don't insist */
1344 if (ret < try)
1345 break;
1346 }
1347 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001348 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001349 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001350 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1351 /* handshake is running, and it may need to re-enable write */
1352 conn->flags |= CO_FL_SSL_WAIT_HS;
1353 __conn_sock_want_send(conn);
1354 break;
1355 }
Emeric Brun46591952012-05-18 15:47:34 +02001356 /* we need to poll to retry a write later */
1357 __conn_data_poll_send(conn);
1358 break;
1359 }
1360 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001361 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001362 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001363 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001364 break;
1365 }
1366 goto out_error;
1367 }
1368 }
1369 return done;
1370
1371 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001372 /* Clear openssl global errors stack */
1373 ERR_clear_error();
1374
Emeric Brun46591952012-05-18 15:47:34 +02001375 conn->flags |= CO_FL_ERROR;
1376 return done;
1377}
1378
Emeric Brun46591952012-05-18 15:47:34 +02001379static void ssl_sock_close(struct connection *conn) {
1380
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001381 if (conn->xprt_ctx) {
1382 SSL_free(conn->xprt_ctx);
1383 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001384 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001385 }
Emeric Brun46591952012-05-18 15:47:34 +02001386}
1387
1388/* This function tries to perform a clean shutdown on an SSL connection, and in
1389 * any case, flags the connection as reusable if no handshake was in progress.
1390 */
1391static void ssl_sock_shutw(struct connection *conn, int clean)
1392{
1393 if (conn->flags & CO_FL_HANDSHAKE)
1394 return;
1395 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001396 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1397 /* Clear openssl global errors stack */
1398 ERR_clear_error();
1399 }
Emeric Brun46591952012-05-18 15:47:34 +02001400
1401 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001402 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001403}
1404
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001405/* used for logging, may be changed for a sample fetch later */
1406const char *ssl_sock_get_cipher_name(struct connection *conn)
1407{
1408 if (!conn->xprt && !conn->xprt_ctx)
1409 return NULL;
1410 return SSL_get_cipher_name(conn->xprt_ctx);
1411}
1412
1413/* used for logging, may be changed for a sample fetch later */
1414const char *ssl_sock_get_proto_version(struct connection *conn)
1415{
1416 if (!conn->xprt && !conn->xprt_ctx)
1417 return NULL;
1418 return SSL_get_version(conn->xprt_ctx);
1419}
1420
Willy Tarreau8d598402012-10-22 17:58:39 +02001421/* Extract a serial from a cert, and copy it to a chunk.
1422 * Returns 1 if serial is found and copied, 0 if no serial found and
1423 * -1 if output is not large enough.
1424 */
1425static int
1426ssl_sock_get_serial(X509 *crt, struct chunk *out)
1427{
1428 ASN1_INTEGER *serial;
1429
1430 serial = X509_get_serialNumber(crt);
1431 if (!serial)
1432 return 0;
1433
1434 if (out->size < serial->length)
1435 return -1;
1436
1437 memcpy(out->str, serial->data, serial->length);
1438 out->len = serial->length;
1439 return 1;
1440}
1441
Emeric Brunce5ad802012-10-22 14:11:22 +02001442
1443/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1444 * Returns 1 if serial is found and copied, 0 if no valid time found
1445 * and -1 if output is not large enough.
1446 */
1447static int
1448ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1449{
1450 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1451 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1452
1453 if (gentm->length < 12)
1454 return 0;
1455 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1456 return 0;
1457 if (out->size < gentm->length-2)
1458 return -1;
1459
1460 memcpy(out->str, gentm->data+2, gentm->length-2);
1461 out->len = gentm->length-2;
1462 return 1;
1463 }
1464 else if (tm->type == V_ASN1_UTCTIME) {
1465 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1466
1467 if (utctm->length < 10)
1468 return 0;
1469 if (utctm->data[0] >= 0x35)
1470 return 0;
1471 if (out->size < utctm->length)
1472 return -1;
1473
1474 memcpy(out->str, utctm->data, utctm->length);
1475 out->len = utctm->length;
1476 return 1;
1477 }
1478
1479 return 0;
1480}
1481
Emeric Brun87855892012-10-17 17:39:35 +02001482/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1483 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1484 */
1485static int
1486ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1487{
1488 X509_NAME_ENTRY *ne;
1489 int i, j, n;
1490 int cur = 0;
1491 const char *s;
1492 char tmp[128];
1493
1494 out->len = 0;
1495 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1496 if (pos < 0)
1497 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1498 else
1499 j = i;
1500
1501 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1502 n = OBJ_obj2nid(ne->object);
1503 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1504 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1505 s = tmp;
1506 }
1507
1508 if (chunk_strcasecmp(entry, s) != 0)
1509 continue;
1510
1511 if (pos < 0)
1512 cur--;
1513 else
1514 cur++;
1515
1516 if (cur != pos)
1517 continue;
1518
1519 if (ne->value->length > out->size)
1520 return -1;
1521
1522 memcpy(out->str, ne->value->data, ne->value->length);
1523 out->len = ne->value->length;
1524 return 1;
1525 }
1526
1527 return 0;
1528
1529}
1530
1531/* Extract and format full DN from a X509_NAME and copy result into a chunk
1532 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1533 */
1534static int
1535ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1536{
1537 X509_NAME_ENTRY *ne;
1538 int i, n, ln;
1539 int l = 0;
1540 const char *s;
1541 char *p;
1542 char tmp[128];
1543
1544 out->len = 0;
1545 p = out->str;
1546 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1547 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1548 n = OBJ_obj2nid(ne->object);
1549 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1550 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1551 s = tmp;
1552 }
1553 ln = strlen(s);
1554
1555 l += 1 + ln + 1 + ne->value->length;
1556 if (l > out->size)
1557 return -1;
1558 out->len = l;
1559
1560 *(p++)='/';
1561 memcpy(p, s, ln);
1562 p += ln;
1563 *(p++)='=';
1564 memcpy(p, ne->value->data, ne->value->length);
1565 p += ne->value->length;
1566 }
1567
1568 if (!out->len)
1569 return 0;
1570
1571 return 1;
1572}
1573
Willy Tarreau7875d092012-09-10 08:20:03 +02001574/***** Below are some sample fetching functions for ACL/patterns *****/
1575
Emeric Brune64aef12012-09-21 13:15:06 +02001576/* boolean, returns true if client cert was present */
1577static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001578smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1579 const struct arg *args, struct sample *smp)
Emeric Brune64aef12012-09-21 13:15:06 +02001580{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001581 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001582 return 0;
1583
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001584 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001585 smp->flags |= SMP_F_MAY_CHANGE;
1586 return 0;
1587 }
1588
1589 smp->flags = 0;
1590 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001591 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001592
1593 return 1;
1594}
1595
Willy Tarreau8d598402012-10-22 17:58:39 +02001596/* bin, returns serial in a binary chunk */
1597static int
1598smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1599 const struct arg *args, struct sample *smp)
1600{
1601 X509 *crt = NULL;
1602 int ret = 0;
1603 struct chunk *smp_trash;
1604
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001605 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001606 return 0;
1607
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001608 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001609 smp->flags |= SMP_F_MAY_CHANGE;
1610 return 0;
1611 }
1612
1613 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001614 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001615 if (!crt)
1616 goto out;
1617
Willy Tarreau47ca5452012-12-23 20:22:19 +01001618 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001619 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1620 goto out;
1621
1622 smp->data.str = *smp_trash;
1623 smp->type = SMP_T_BIN;
1624 ret = 1;
1625out:
1626 if (crt)
1627 X509_free(crt);
1628 return ret;
1629}
Emeric Brune64aef12012-09-21 13:15:06 +02001630
Emeric Brunce5ad802012-10-22 14:11:22 +02001631/*str, returns notafter date in ASN1_UTCTIME format */
1632static int
1633smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1634 const struct arg *args, struct sample *smp)
1635{
1636 X509 *crt = NULL;
1637 int ret = 0;
1638 struct chunk *smp_trash;
1639
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001640 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001641 return 0;
1642
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001643 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001644 smp->flags |= SMP_F_MAY_CHANGE;
1645 return 0;
1646 }
1647
1648 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001649 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001650 if (!crt)
1651 goto out;
1652
Willy Tarreau47ca5452012-12-23 20:22:19 +01001653 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001654 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1655 goto out;
1656
1657 smp->data.str = *smp_trash;
1658 smp->type = SMP_T_STR;
1659 ret = 1;
1660out:
1661 if (crt)
1662 X509_free(crt);
1663 return ret;
1664}
1665
Emeric Brun87855892012-10-17 17:39:35 +02001666/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1667static int
1668smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1669 const struct arg *args, struct sample *smp)
1670{
1671 X509 *crt = NULL;
1672 X509_NAME *name;
1673 int ret = 0;
1674 struct chunk *smp_trash;
1675
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001676 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001677 return 0;
1678
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001679 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001680 smp->flags |= SMP_F_MAY_CHANGE;
1681 return 0;
1682 }
1683
1684 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001685 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001686 if (!crt)
1687 goto out;
1688
1689 name = X509_get_issuer_name(crt);
1690 if (!name)
1691 goto out;
1692
Willy Tarreau47ca5452012-12-23 20:22:19 +01001693 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001694 if (args && args[0].type == ARGT_STR) {
1695 int pos = 1;
1696
1697 if (args[1].type == ARGT_SINT)
1698 pos = args[1].data.sint;
1699 else if (args[1].type == ARGT_UINT)
1700 pos =(int)args[1].data.uint;
1701
1702 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1703 goto out;
1704 }
1705 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1706 goto out;
1707
1708 smp->type = SMP_T_STR;
1709 smp->data.str = *smp_trash;
1710 ret = 1;
1711out:
1712 if (crt)
1713 X509_free(crt);
1714 return ret;
1715}
1716
Emeric Brunce5ad802012-10-22 14:11:22 +02001717/*str, returns notbefore date in ASN1_UTCTIME format */
1718static int
1719smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1720 const struct arg *args, struct sample *smp)
1721{
1722 X509 *crt = NULL;
1723 int ret = 0;
1724 struct chunk *smp_trash;
1725
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001726 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001727 return 0;
1728
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001729 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001730 smp->flags |= SMP_F_MAY_CHANGE;
1731 return 0;
1732 }
1733
1734 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001735 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001736 if (!crt)
1737 goto out;
1738
Willy Tarreau47ca5452012-12-23 20:22:19 +01001739 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001740 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1741 goto out;
1742
1743 smp->data.str = *smp_trash;
1744 smp->type = SMP_T_STR;
1745 ret = 1;
1746out:
1747 if (crt)
1748 X509_free(crt);
1749 return ret;
1750}
1751
Emeric Brun87855892012-10-17 17:39:35 +02001752/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1753static int
1754smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1755 const struct arg *args, struct sample *smp)
1756{
1757 X509 *crt = NULL;
1758 X509_NAME *name;
1759 int ret = 0;
1760 struct chunk *smp_trash;
1761
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001762 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001763 return 0;
1764
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001765 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001766 smp->flags |= SMP_F_MAY_CHANGE;
1767 return 0;
1768 }
1769
1770 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001771 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001772 if (!crt)
1773 goto out;
1774
1775 name = X509_get_subject_name(crt);
1776 if (!name)
1777 goto out;
1778
Willy Tarreau47ca5452012-12-23 20:22:19 +01001779 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001780 if (args && args[0].type == ARGT_STR) {
1781 int pos = 1;
1782
1783 if (args[1].type == ARGT_SINT)
1784 pos = args[1].data.sint;
1785 else if (args[1].type == ARGT_UINT)
1786 pos =(int)args[1].data.uint;
1787
1788 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1789 goto out;
1790 }
1791 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1792 goto out;
1793
1794 smp->type = SMP_T_STR;
1795 smp->data.str = *smp_trash;
1796 ret = 1;
1797out:
1798 if (crt)
1799 X509_free(crt);
1800 return ret;
1801}
Emeric Brun9143d372012-12-20 15:44:16 +01001802
1803/* integer, returns true if current session use a client certificate */
1804static int
1805smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1806 const struct arg *args, struct sample *smp)
1807{
1808 X509 *crt;
1809
1810 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
1811 return 0;
1812
1813 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
1814 smp->flags |= SMP_F_MAY_CHANGE;
1815 return 0;
1816 }
1817
1818 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
1819 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
1820 if (crt) {
1821 X509_free(crt);
1822 }
1823
1824 smp->type = SMP_T_BOOL;
1825 smp->data.uint = (crt != NULL);
1826 return 1;
1827}
1828
Emeric Bruna7359fd2012-10-17 15:03:11 +02001829/* integer, returns the client certificate version */
1830static int
1831smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1832 const struct arg *args, struct sample *smp)
1833{
1834 X509 *crt;
1835
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001836 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001837 return 0;
1838
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001839 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001840 smp->flags |= SMP_F_MAY_CHANGE;
1841 return 0;
1842 }
1843
1844 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001845 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001846 if (!crt)
1847 return 0;
1848
1849 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1850 X509_free(crt);
1851 smp->type = SMP_T_UINT;
1852
1853 return 1;
1854}
1855
Emeric Brun7f56e742012-10-19 18:15:40 +02001856/* str, returns the client certificate sig alg */
1857static int
1858smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1859 const struct arg *args, struct sample *smp)
1860{
1861 X509 *crt;
1862 int nid;
1863
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001864 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02001865 return 0;
1866
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001867 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02001868 smp->flags |= SMP_F_MAY_CHANGE;
1869 return 0;
1870 }
1871
1872 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001873 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02001874 if (!crt)
1875 return 0;
1876
1877 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1878
1879 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1880 if (!smp->data.str.str)
1881 return 0;
1882
1883 smp->type = SMP_T_CSTR;
1884 smp->data.str.len = strlen(smp->data.str.str);
1885 X509_free(crt);
1886
1887 return 1;
1888}
1889
Emeric Brun521a0112012-10-22 12:22:55 +02001890/* str, returns the client certificate key alg */
1891static int
1892smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1893 const struct arg *args, struct sample *smp)
1894{
1895 X509 *crt;
1896 int nid;
1897
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001898 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02001899 return 0;
1900
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001901 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02001902 smp->flags |= SMP_F_MAY_CHANGE;
1903 return 0;
1904 }
1905
1906 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001907 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02001908 if (!crt)
1909 return 0;
1910
1911 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1912
1913 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1914 if (!smp->data.str.str)
1915 return 0;
1916
1917 smp->type = SMP_T_CSTR;
1918 smp->data.str.len = strlen(smp->data.str.str);
1919 X509_free(crt);
1920
1921 return 1;
1922}
1923
Emeric Brun2525b6b2012-10-18 15:59:43 +02001924/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02001925static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001926smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau7875d092012-09-10 08:20:03 +02001927 const struct arg *args, struct sample *smp)
1928{
1929 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001930 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02001931 return 1;
1932}
1933
Emeric Brun2525b6b2012-10-18 15:59:43 +02001934/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02001935static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001936smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1937 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02001938{
1939#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1940 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001941 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock) &&
1942 l4->si[0].conn->xprt_ctx &&
1943 SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02001944 return 1;
1945#else
1946 return 0;
1947#endif
1948}
1949
Willy Tarreau8d598402012-10-22 17:58:39 +02001950/* bin, returns serial in a binary chunk */
1951static int
1952smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1953 const struct arg *args, struct sample *smp)
1954{
1955 X509 *crt = NULL;
1956 int ret = 0;
1957 struct chunk *smp_trash;
1958
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001959 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001960 return 0;
1961
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001962 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001963 smp->flags |= SMP_F_MAY_CHANGE;
1964 return 0;
1965 }
1966
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001967 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001968 if (!crt)
1969 goto out;
1970
Willy Tarreau47ca5452012-12-23 20:22:19 +01001971 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001972 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1973 goto out;
1974
1975 smp->data.str = *smp_trash;
1976 smp->type = SMP_T_BIN;
1977 ret = 1;
1978out:
1979 return ret;
1980}
Emeric Brunce5ad802012-10-22 14:11:22 +02001981/*str, returns notafter date in ASN1_UTCTIME format */
1982static int
1983smp_fetch_ssl_f_notafter(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_notAfter(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}
2012
2013/*str, returns notbefore date in ASN1_UTCTIME format */
2014static int
2015smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2016 const struct arg *args, struct sample *smp)
2017{
2018 X509 *crt = NULL;
2019 int ret = 0;
2020 struct chunk *smp_trash;
2021
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002022 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02002023 return 0;
2024
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002025 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002026 smp->flags |= SMP_F_MAY_CHANGE;
2027 return 0;
2028 }
2029
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002030 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002031 if (!crt)
2032 goto out;
2033
Willy Tarreau47ca5452012-12-23 20:22:19 +01002034 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002035 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
2036 goto out;
2037
2038 smp->data.str = *smp_trash;
2039 smp->type = SMP_T_STR;
2040 ret = 1;
2041out:
2042 return ret;
2043}
Willy Tarreau8d598402012-10-22 17:58:39 +02002044
Emeric Bruna7359fd2012-10-17 15:03:11 +02002045/* integer, returns the frontend certificate version */
2046static int
2047smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2048 const struct arg *args, struct sample *smp)
2049{
2050 X509 *crt;
2051
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002052 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002053 return 0;
2054
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002055 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002056 smp->flags |= SMP_F_MAY_CHANGE;
2057 return 0;
2058 }
2059
2060 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002061 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002062 if (!crt)
2063 return 0;
2064
2065 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2066 smp->type = SMP_T_UINT;
2067
2068 return 1;
2069}
2070
Emeric Brun7f56e742012-10-19 18:15:40 +02002071/* str, returns the client certificate sig alg */
2072static int
2073smp_fetch_ssl_f_sig_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 Brun7f56e742012-10-19 18:15:40 +02002080 return 0;
2081
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002082 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +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 Brun7f56e742012-10-19 18:15:40 +02002088 if (!crt)
2089 return 0;
2090
2091 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->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 Brun521a0112012-10-22 12:22:55 +02002103/* str, returns the client certificate key alg */
2104static int
2105smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2106 const struct arg *args, struct sample *smp)
2107{
2108 X509 *crt;
2109 int nid;
2110
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002111 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002112 return 0;
2113
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002114 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002115 smp->flags |= SMP_F_MAY_CHANGE;
2116 return 0;
2117 }
2118
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002119 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002120 if (!crt)
2121 return 0;
2122
2123 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2124
2125 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2126 if (!smp->data.str.str)
2127 return 0;
2128
2129 smp->type = SMP_T_CSTR;
2130 smp->data.str.len = strlen(smp->data.str.str);
2131
2132 return 1;
2133}
2134
Emeric Brun87855892012-10-17 17:39:35 +02002135/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2136static int
2137smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2138 const struct arg *args, struct sample *smp)
2139{
2140 X509 *crt = NULL;
2141 X509_NAME *name;
2142 int ret = 0;
2143 struct chunk *smp_trash;
2144
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002145 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002146 return 0;
2147
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002148 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002149 smp->flags |= SMP_F_MAY_CHANGE;
2150 return 0;
2151 }
2152
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002153 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002154 if (!crt)
2155 goto out;
2156
2157 name = X509_get_issuer_name(crt);
2158 if (!name)
2159 goto out;
2160
Willy Tarreau47ca5452012-12-23 20:22:19 +01002161 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002162 if (args && args[0].type == ARGT_STR) {
2163 int pos = 1;
2164
2165 if (args[1].type == ARGT_SINT)
2166 pos = args[1].data.sint;
2167 else if (args[1].type == ARGT_UINT)
2168 pos =(int)args[1].data.uint;
2169
2170 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2171 goto out;
2172 }
2173 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2174 goto out;
2175
2176 smp->type = SMP_T_STR;
2177 smp->data.str = *smp_trash;
2178 ret = 1;
2179out:
2180 return ret;
2181}
2182
2183/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2184static int
2185smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2186 const struct arg *args, struct sample *smp)
2187{
2188 X509 *crt = NULL;
2189 X509_NAME *name;
2190 int ret = 0;
2191 struct chunk *smp_trash;
2192
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002193 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002194 return 0;
2195
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002196 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002197 smp->flags |= SMP_F_MAY_CHANGE;
2198 return 0;
2199 }
2200
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002201 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002202 if (!crt)
2203 goto out;
2204
2205 name = X509_get_subject_name(crt);
2206 if (!name)
2207 goto out;
2208
Willy Tarreau47ca5452012-12-23 20:22:19 +01002209 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002210 if (args && args[0].type == ARGT_STR) {
2211 int pos = 1;
2212
2213 if (args[1].type == ARGT_SINT)
2214 pos = args[1].data.sint;
2215 else if (args[1].type == ARGT_UINT)
2216 pos =(int)args[1].data.uint;
2217
2218 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2219 goto out;
2220 }
2221 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2222 goto out;
2223
2224 smp->type = SMP_T_STR;
2225 smp->data.str = *smp_trash;
2226 ret = 1;
2227out:
2228 return ret;
2229}
2230
Emeric Brun589fcad2012-10-16 14:13:26 +02002231static int
2232smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2233 const struct arg *args, struct sample *smp)
2234{
2235 smp->flags = 0;
2236
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002237 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002238 return 0;
2239
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002240 smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002241 if (!smp->data.str.str)
2242 return 0;
2243
2244 smp->type = SMP_T_CSTR;
2245 smp->data.str.len = strlen(smp->data.str.str);
2246
2247 return 1;
2248}
2249
2250static int
2251smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2252 const struct arg *args, struct sample *smp)
2253{
2254 smp->flags = 0;
2255
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002256 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002257 return 0;
2258
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002259 if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
Emeric Brun589fcad2012-10-16 14:13:26 +02002260 return 0;
2261
2262 smp->type = SMP_T_UINT;
2263
2264 return 1;
2265}
2266
2267static int
2268smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2269 const struct arg *args, struct sample *smp)
2270{
2271 smp->flags = 0;
2272
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002273 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002274 return 0;
2275
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002276 smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002277 if (!smp->data.uint)
2278 return 0;
2279
2280 smp->type = SMP_T_UINT;
2281
2282 return 1;
2283}
2284
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002285#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002286static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002287smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2288 const struct arg *args, struct sample *smp)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002289{
Willy Tarreaua33c6542012-10-15 13:19:06 +02002290 smp->flags = 0;
2291 smp->type = SMP_T_CSTR;
2292
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002293 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002294 return 0;
2295
2296 smp->data.str.str = NULL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002297 SSL_get0_next_proto_negotiated(l4->si[0].conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002298 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2299
2300 if (!smp->data.str.str)
2301 return 0;
2302
2303 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002304}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002305#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002306
Willy Tarreauab861d32013-04-02 02:30:41 +02002307#ifdef OPENSSL_ALPN_NEGOTIATED
2308static int
2309smp_fetch_ssl_fc_alpn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2310 const struct arg *args, struct sample *smp)
2311{
2312 smp->flags = 0;
2313 smp->type = SMP_T_CSTR;
2314
2315 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
2316 return 0;
2317
2318 smp->data.str.str = NULL;
2319 SSL_get0_alpn_negotiated(l4->si[0].conn->xprt_ctx,
2320 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2321
2322 if (!smp->data.str.str)
2323 return 0;
2324
2325 return 1;
2326}
2327#endif
2328
Willy Tarreaua33c6542012-10-15 13:19:06 +02002329static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002330smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2331 const struct arg *args, struct sample *smp)
2332{
2333 smp->flags = 0;
2334
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002335 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002336 return 0;
2337
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002338 smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002339 if (!smp->data.str.str)
2340 return 0;
2341
2342 smp->type = SMP_T_CSTR;
2343 smp->data.str.len = strlen(smp->data.str.str);
2344
2345 return 1;
2346}
2347
2348static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002349smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2350 const struct arg *args, struct sample *smp)
2351{
2352#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2353 SSL_SESSION *sess;
2354
2355 smp->flags = 0;
2356 smp->type = SMP_T_CBIN;
2357
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002358 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunfe68f682012-10-16 14:59:28 +02002359 return 0;
2360
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002361 sess = SSL_get_session(l4->si[0].conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002362 if (!sess)
2363 return 0;
2364
2365 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2366 if (!smp->data.str.str || !&smp->data.str.len)
2367 return 0;
2368
2369 return 1;
2370#else
2371 return 0;
2372#endif
2373}
2374
2375static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002376smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2377 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02002378{
2379#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2380 smp->flags = 0;
2381 smp->type = SMP_T_CSTR;
2382
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002383 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau7875d092012-09-10 08:20:03 +02002384 return 0;
2385
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002386 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 +02002387 if (!smp->data.str.str)
2388 return 0;
2389
Willy Tarreau7875d092012-09-10 08:20:03 +02002390 smp->data.str.len = strlen(smp->data.str.str);
2391 return 1;
2392#else
2393 return 0;
2394#endif
2395}
2396
Emeric Brun2525b6b2012-10-18 15:59:43 +02002397/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002398static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002399smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002400 const struct arg *args, struct sample *smp)
2401{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002402 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002403 return 0;
2404
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002405 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002406 smp->flags = SMP_F_MAY_CHANGE;
2407 return 0;
2408 }
2409
2410 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002411 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002412 smp->flags = 0;
2413
2414 return 1;
2415}
2416
Emeric Brun2525b6b2012-10-18 15:59:43 +02002417/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002418static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002419smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002420 const struct arg *args, struct sample *smp)
2421{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002422 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002423 return 0;
2424
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002425 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002426 smp->flags = SMP_F_MAY_CHANGE;
2427 return 0;
2428 }
2429
2430 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002431 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002432 smp->flags = 0;
2433
2434 return 1;
2435}
2436
Emeric Brun2525b6b2012-10-18 15:59:43 +02002437/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002438static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002439smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2440 const struct arg *args, struct sample *smp)
Emeric Brunf282a812012-09-21 15:27:54 +02002441{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002442 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002443 return 0;
2444
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002445 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002446 smp->flags = SMP_F_MAY_CHANGE;
2447 return 0;
2448 }
2449
2450 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002451 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002452 smp->flags = 0;
2453
2454 return 1;
2455}
2456
Emeric Brun2525b6b2012-10-18 15:59:43 +02002457/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002458static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002459smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2460 const struct arg *args, struct sample *smp)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002461{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002462 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002463 return 0;
2464
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002465 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002466 smp->flags = SMP_F_MAY_CHANGE;
2467 return 0;
2468 }
2469
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002470 if (!l4->si[0].conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002471 return 0;
2472
2473 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002474 smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002475 smp->flags = 0;
2476
2477 return 1;
2478}
2479
Emeric Brunfb510ea2012-10-05 12:00:26 +02002480/* parse the "ca-file" bind keyword */
2481static 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 +02002482{
2483 if (!*args[cur_arg + 1]) {
2484 if (err)
2485 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2486 return ERR_ALERT | ERR_FATAL;
2487 }
2488
Emeric Brunef42d922012-10-11 16:11:36 +02002489 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2490 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2491 else
2492 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002493
Emeric Brund94b3fe2012-09-20 18:23:56 +02002494 return 0;
2495}
2496
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002497/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002498static 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 +02002499{
2500 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002501 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002502 return ERR_ALERT | ERR_FATAL;
2503 }
2504
Emeric Brun76d88952012-10-05 15:47:31 +02002505 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002506 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002507 return 0;
2508}
2509
2510/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002511static 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 +02002512{
Emeric Brunc8e8d122012-10-02 18:42:10 +02002513 char path[PATH_MAX];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002514 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002515 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002516 return ERR_ALERT | ERR_FATAL;
2517 }
2518
Emeric Brunc8e8d122012-10-02 18:42:10 +02002519 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
2520 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > PATH_MAX) {
2521 memprintf(err, "'%s' : path too long", args[cur_arg]);
2522 return ERR_ALERT | ERR_FATAL;
2523 }
2524 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2525 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2526 return ERR_ALERT | ERR_FATAL;
2527
2528 return 0;
2529 }
2530
Willy Tarreau4348fad2012-09-20 16:48:07 +02002531 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002532 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002533
2534 return 0;
2535}
2536
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002537/* parse the "crt-list" bind keyword */
2538static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2539{
2540 if (!*args[cur_arg + 1]) {
2541 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
2542 return ERR_ALERT | ERR_FATAL;
2543 }
2544
Willy Tarreauad1731d2013-04-02 17:35:58 +02002545 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
2546 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002547 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02002548 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002549
2550 return 0;
2551}
2552
Emeric Brunfb510ea2012-10-05 12:00:26 +02002553/* parse the "crl-file" bind keyword */
2554static 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 +02002555{
Emeric Brun051cdab2012-10-02 19:25:50 +02002556#ifndef X509_V_FLAG_CRL_CHECK
2557 if (err)
2558 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2559 return ERR_ALERT | ERR_FATAL;
2560#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002561 if (!*args[cur_arg + 1]) {
2562 if (err)
2563 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2564 return ERR_ALERT | ERR_FATAL;
2565 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002566
Emeric Brunef42d922012-10-11 16:11:36 +02002567 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2568 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2569 else
2570 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002571
Emeric Brun2b58d042012-09-20 17:10:03 +02002572 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002573#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002574}
2575
2576/* parse the "ecdhe" bind keyword keywords */
2577static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2578{
2579#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2580 if (err)
2581 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2582 return ERR_ALERT | ERR_FATAL;
2583#elif defined(OPENSSL_NO_ECDH)
2584 if (err)
2585 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2586 return ERR_ALERT | ERR_FATAL;
2587#else
2588 if (!*args[cur_arg + 1]) {
2589 if (err)
2590 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2591 return ERR_ALERT | ERR_FATAL;
2592 }
2593
2594 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002595
2596 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002597#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002598}
2599
Emeric Brun81c00f02012-09-21 14:31:21 +02002600/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2601static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2602{
2603 int code;
2604 char *p = args[cur_arg + 1];
2605 unsigned long long *ignerr = &conf->crt_ignerr;
2606
2607 if (!*p) {
2608 if (err)
2609 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2610 return ERR_ALERT | ERR_FATAL;
2611 }
2612
2613 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2614 ignerr = &conf->ca_ignerr;
2615
2616 if (strcmp(p, "all") == 0) {
2617 *ignerr = ~0ULL;
2618 return 0;
2619 }
2620
2621 while (p) {
2622 code = atoi(p);
2623 if ((code <= 0) || (code > 63)) {
2624 if (err)
2625 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2626 args[cur_arg], code, args[cur_arg + 1]);
2627 return ERR_ALERT | ERR_FATAL;
2628 }
2629 *ignerr |= 1ULL << code;
2630 p = strchr(p, ',');
2631 if (p)
2632 p++;
2633 }
2634
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002635 return 0;
2636}
2637
2638/* parse the "force-sslv3" bind keyword */
2639static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2640{
2641 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2642 return 0;
2643}
2644
2645/* parse the "force-tlsv10" bind keyword */
2646static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2647{
2648 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002649 return 0;
2650}
2651
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002652/* parse the "force-tlsv11" bind keyword */
2653static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2654{
2655#if SSL_OP_NO_TLSv1_1
2656 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
2657 return 0;
2658#else
2659 if (err)
2660 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
2661 return ERR_ALERT | ERR_FATAL;
2662#endif
2663}
2664
2665/* parse the "force-tlsv12" bind keyword */
2666static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2667{
2668#if SSL_OP_NO_TLSv1_2
2669 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
2670 return 0;
2671#else
2672 if (err)
2673 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
2674 return ERR_ALERT | ERR_FATAL;
2675#endif
2676}
2677
2678
Emeric Brun2d0c4822012-10-02 13:45:20 +02002679/* parse the "no-tls-tickets" bind keyword */
2680static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2681{
Emeric Brun89675492012-10-05 13:48:26 +02002682 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02002683 return 0;
2684}
2685
Emeric Brun2d0c4822012-10-02 13:45:20 +02002686
Emeric Brun9b3009b2012-10-05 11:55:06 +02002687/* parse the "no-sslv3" bind keyword */
2688static 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 +02002689{
Emeric Brun89675492012-10-05 13:48:26 +02002690 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002691 return 0;
2692}
2693
Emeric Brun9b3009b2012-10-05 11:55:06 +02002694/* parse the "no-tlsv10" bind keyword */
2695static 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 +02002696{
Emeric Brun89675492012-10-05 13:48:26 +02002697 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002698 return 0;
2699}
2700
Emeric Brun9b3009b2012-10-05 11:55:06 +02002701/* parse the "no-tlsv11" bind keyword */
2702static 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 +02002703{
Emeric Brun89675492012-10-05 13:48:26 +02002704 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002705 return 0;
2706}
2707
Emeric Brun9b3009b2012-10-05 11:55:06 +02002708/* parse the "no-tlsv12" bind keyword */
2709static 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 +02002710{
Emeric Brun89675492012-10-05 13:48:26 +02002711 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002712 return 0;
2713}
2714
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002715/* parse the "npn" bind keyword */
2716static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2717{
2718#ifdef OPENSSL_NPN_NEGOTIATED
2719 char *p1, *p2;
2720
2721 if (!*args[cur_arg + 1]) {
2722 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
2723 return ERR_ALERT | ERR_FATAL;
2724 }
2725
2726 free(conf->npn_str);
2727
2728 /* the NPN string is built as a suite of (<len> <name>)* */
2729 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
2730 conf->npn_str = calloc(1, conf->npn_len);
2731 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
2732
2733 /* replace commas with the name length */
2734 p1 = conf->npn_str;
2735 p2 = p1 + 1;
2736 while (1) {
2737 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
2738 if (!p2)
2739 p2 = p1 + 1 + strlen(p1 + 1);
2740
2741 if (p2 - (p1 + 1) > 255) {
2742 *p2 = '\0';
2743 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2744 return ERR_ALERT | ERR_FATAL;
2745 }
2746
2747 *p1 = p2 - (p1 + 1);
2748 p1 = p2;
2749
2750 if (!*p2)
2751 break;
2752
2753 *(p2++) = '\0';
2754 }
2755 return 0;
2756#else
2757 if (err)
2758 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
2759 return ERR_ALERT | ERR_FATAL;
2760#endif
2761}
2762
Willy Tarreauab861d32013-04-02 02:30:41 +02002763/* parse the "alpn" bind keyword */
2764static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2765{
2766#ifdef OPENSSL_ALPN_NEGOTIATED
2767 char *p1, *p2;
2768
2769 if (!*args[cur_arg + 1]) {
2770 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
2771 return ERR_ALERT | ERR_FATAL;
2772 }
2773
2774 free(conf->alpn_str);
2775
2776 /* the ALPN string is built as a suite of (<len> <name>)* */
2777 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
2778 conf->alpn_str = calloc(1, conf->alpn_len);
2779 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
2780
2781 /* replace commas with the name length */
2782 p1 = conf->alpn_str;
2783 p2 = p1 + 1;
2784 while (1) {
2785 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
2786 if (!p2)
2787 p2 = p1 + 1 + strlen(p1 + 1);
2788
2789 if (p2 - (p1 + 1) > 255) {
2790 *p2 = '\0';
2791 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2792 return ERR_ALERT | ERR_FATAL;
2793 }
2794
2795 *p1 = p2 - (p1 + 1);
2796 p1 = p2;
2797
2798 if (!*p2)
2799 break;
2800
2801 *(p2++) = '\0';
2802 }
2803 return 0;
2804#else
2805 if (err)
2806 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
2807 return ERR_ALERT | ERR_FATAL;
2808#endif
2809}
2810
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002811/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002812static 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 +02002813{
Willy Tarreau81796be2012-09-22 19:11:47 +02002814 struct listener *l;
2815
Willy Tarreau4348fad2012-09-20 16:48:07 +02002816 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02002817
2818 if (global.listen_default_ciphers && !conf->ciphers)
2819 conf->ciphers = strdup(global.listen_default_ciphers);
2820
Willy Tarreau81796be2012-09-22 19:11:47 +02002821 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002822 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02002823
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002824 return 0;
2825}
2826
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002827/* parse the "strict-sni" bind keyword */
2828static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2829{
2830 conf->strict_sni = 1;
2831 return 0;
2832}
2833
Emeric Brund94b3fe2012-09-20 18:23:56 +02002834/* parse the "verify" bind keyword */
2835static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2836{
2837 if (!*args[cur_arg + 1]) {
2838 if (err)
2839 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
2840 return ERR_ALERT | ERR_FATAL;
2841 }
2842
2843 if (strcmp(args[cur_arg + 1], "none") == 0)
2844 conf->verify = SSL_VERIFY_NONE;
2845 else if (strcmp(args[cur_arg + 1], "optional") == 0)
2846 conf->verify = SSL_VERIFY_PEER;
2847 else if (strcmp(args[cur_arg + 1], "required") == 0)
2848 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2849 else {
2850 if (err)
2851 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
2852 args[cur_arg], args[cur_arg + 1]);
2853 return ERR_ALERT | ERR_FATAL;
2854 }
2855
2856 return 0;
2857}
2858
Willy Tarreau92faadf2012-10-10 23:04:25 +02002859/************** "server" keywords ****************/
2860
Emeric Brunef42d922012-10-11 16:11:36 +02002861/* parse the "ca-file" server keyword */
2862static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2863{
2864 if (!*args[*cur_arg + 1]) {
2865 if (err)
2866 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
2867 return ERR_ALERT | ERR_FATAL;
2868 }
2869
2870 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2871 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2872 else
2873 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
2874
2875 return 0;
2876}
2877
Willy Tarreau92faadf2012-10-10 23:04:25 +02002878/* parse the "check-ssl" server keyword */
2879static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2880{
2881 newsrv->check.use_ssl = 1;
2882 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2883 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2884 return 0;
2885}
2886
2887/* parse the "ciphers" server keyword */
2888static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2889{
2890 if (!*args[*cur_arg + 1]) {
2891 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
2892 return ERR_ALERT | ERR_FATAL;
2893 }
2894
2895 free(newsrv->ssl_ctx.ciphers);
2896 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
2897 return 0;
2898}
2899
Emeric Brunef42d922012-10-11 16:11:36 +02002900/* parse the "crl-file" server keyword */
2901static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2902{
2903#ifndef X509_V_FLAG_CRL_CHECK
2904 if (err)
2905 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
2906 return ERR_ALERT | ERR_FATAL;
2907#else
2908 if (!*args[*cur_arg + 1]) {
2909 if (err)
2910 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
2911 return ERR_ALERT | ERR_FATAL;
2912 }
2913
2914 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2915 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2916 else
2917 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
2918
2919 return 0;
2920#endif
2921}
2922
Emeric Bruna7aa3092012-10-26 12:58:00 +02002923/* parse the "crt" server keyword */
2924static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2925{
2926 if (!*args[*cur_arg + 1]) {
2927 if (err)
2928 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
2929 return ERR_ALERT | ERR_FATAL;
2930 }
2931
2932 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
2933 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2934 else
2935 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
2936
2937 return 0;
2938}
Emeric Brunef42d922012-10-11 16:11:36 +02002939
Willy Tarreau92faadf2012-10-10 23:04:25 +02002940/* parse the "force-sslv3" server keyword */
2941static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2942{
2943 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
2944 return 0;
2945}
2946
2947/* parse the "force-tlsv10" server keyword */
2948static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2949{
2950 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
2951 return 0;
2952}
2953
2954/* parse the "force-tlsv11" server keyword */
2955static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2956{
2957#if SSL_OP_NO_TLSv1_1
2958 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
2959 return 0;
2960#else
2961 if (err)
2962 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
2963 return ERR_ALERT | ERR_FATAL;
2964#endif
2965}
2966
2967/* parse the "force-tlsv12" server keyword */
2968static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2969{
2970#if SSL_OP_NO_TLSv1_2
2971 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
2972 return 0;
2973#else
2974 if (err)
2975 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
2976 return ERR_ALERT | ERR_FATAL;
2977#endif
2978}
2979
2980/* parse the "no-sslv3" server keyword */
2981static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2982{
2983 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
2984 return 0;
2985}
2986
2987/* parse the "no-tlsv10" server keyword */
2988static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2989{
2990 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
2991 return 0;
2992}
2993
2994/* parse the "no-tlsv11" server keyword */
2995static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2996{
2997 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
2998 return 0;
2999}
3000
3001/* parse the "no-tlsv12" server keyword */
3002static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3003{
3004 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
3005 return 0;
3006}
3007
Emeric Brunf9c5c472012-10-11 15:28:34 +02003008/* parse the "no-tls-tickets" server keyword */
3009static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3010{
3011 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
3012 return 0;
3013}
3014
Willy Tarreau92faadf2012-10-10 23:04:25 +02003015/* parse the "ssl" server keyword */
3016static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3017{
3018 newsrv->use_ssl = 1;
3019 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3020 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3021 return 0;
3022}
3023
Emeric Brunef42d922012-10-11 16:11:36 +02003024/* parse the "verify" server keyword */
3025static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3026{
3027 if (!*args[*cur_arg + 1]) {
3028 if (err)
3029 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
3030 return ERR_ALERT | ERR_FATAL;
3031 }
3032
3033 if (strcmp(args[*cur_arg + 1], "none") == 0)
3034 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
3035 else if (strcmp(args[*cur_arg + 1], "required") == 0)
3036 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
3037 else {
3038 if (err)
3039 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
3040 args[*cur_arg], args[*cur_arg + 1]);
3041 return ERR_ALERT | ERR_FATAL;
3042 }
3043
3044 return 0;
3045}
3046
Willy Tarreau7875d092012-09-10 08:20:03 +02003047/* Note: must not be declared <const> as its list will be overwritten.
3048 * Please take care of keeping this list alphabetically sorted.
3049 */
3050static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
Willy Tarreau80aca902013-01-07 15:42:20 +01003051 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3052 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3053 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3054 { "ssl_c_i_dn", smp_fetch_ssl_c_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3055 { "ssl_c_key_alg", smp_fetch_ssl_c_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3056 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3057 { "ssl_c_notbefore", smp_fetch_ssl_c_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3058 { "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3059 { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3060 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3061 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3062 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3063 { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3064 { "ssl_f_i_dn", smp_fetch_ssl_f_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3065 { "ssl_f_key_alg", smp_fetch_ssl_f_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3066 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3067 { "ssl_f_notbefore", smp_fetch_ssl_f_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3068 { "ssl_f_sig_alg", smp_fetch_ssl_f_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3069 { "ssl_f_s_dn", smp_fetch_ssl_f_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3070 { "ssl_f_serial", smp_fetch_ssl_f_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3071 { "ssl_f_version", smp_fetch_ssl_f_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3072 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3073 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3074 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3075 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3076 { "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 +02003077#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau80aca902013-01-07 15:42:20 +01003078 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003079#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003080#ifdef OPENSSL_ALPN_NEGOTIATED
3081 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3082#endif
Willy Tarreau80aca902013-01-07 15:42:20 +01003083 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3084 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3085 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_CBIN, SMP_USE_L5CLI },
3086 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreau7875d092012-09-10 08:20:03 +02003087 { NULL, NULL, 0, 0, 0 },
3088}};
3089
3090/* Note: must not be declared <const> as its list will be overwritten.
3091 * Please take care of keeping this list alphabetically sorted.
3092 */
3093static struct acl_kw_list acl_kws = {{ },{
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003094 { "ssl_c_ca_err", NULL, acl_parse_int, acl_match_int },
3095 { "ssl_c_ca_err_depth", NULL, acl_parse_int, acl_match_int },
3096 { "ssl_c_err", NULL, acl_parse_int, acl_match_int },
3097 { "ssl_c_i_dn", NULL, acl_parse_str, acl_match_str },
3098 { "ssl_c_key_alg", NULL, acl_parse_str, acl_match_str },
3099 { "ssl_c_notafter", NULL, acl_parse_str, acl_match_str },
3100 { "ssl_c_notbefore", NULL, acl_parse_str, acl_match_str },
3101 { "ssl_c_sig_alg", NULL, acl_parse_str, acl_match_str },
3102 { "ssl_c_s_dn", NULL, acl_parse_str, acl_match_str },
3103 { "ssl_c_serial", NULL, acl_parse_bin, acl_match_bin },
3104 { "ssl_c_used", NULL, acl_parse_nothing, acl_match_nothing },
3105 { "ssl_c_verify", NULL, acl_parse_int, acl_match_int },
3106 { "ssl_c_version", NULL, acl_parse_int, acl_match_int },
3107 { "ssl_f_i_dn", NULL, acl_parse_str, acl_match_str },
3108 { "ssl_f_key_alg", NULL, acl_parse_str, acl_match_str },
3109 { "ssl_f_notafter", NULL, acl_parse_str, acl_match_str },
3110 { "ssl_f_notbefore", NULL, acl_parse_str, acl_match_str },
3111 { "ssl_f_sig_alg", NULL, acl_parse_str, acl_match_str },
3112 { "ssl_f_s_dn", NULL, acl_parse_str, acl_match_str },
3113 { "ssl_f_serial", NULL, acl_parse_bin, acl_match_bin },
3114 { "ssl_f_version", NULL, acl_parse_int, acl_match_int },
3115 { "ssl_fc", NULL, acl_parse_nothing, acl_match_nothing },
3116 { "ssl_fc_alg_keysize", NULL, acl_parse_int, acl_match_int },
3117 { "ssl_fc_cipher", NULL, acl_parse_str, acl_match_str },
3118 { "ssl_fc_has_crt", NULL, acl_parse_nothing, acl_match_nothing },
3119 { "ssl_fc_has_sni", NULL, acl_parse_nothing, acl_match_nothing },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003120#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003121 { "ssl_fc_npn", NULL, acl_parse_str, acl_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003122#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003123#ifdef OPENSSL_ALPN_NEGOTIATED
3124 { "ssl_fc_alpn", NULL, acl_parse_str, acl_match_str },
3125#endif
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003126 { "ssl_fc_protocol", NULL, acl_parse_str, acl_match_str },
3127 { "ssl_fc_use_keysize", NULL, acl_parse_int, acl_match_int },
3128 { "ssl_fc_sni", "ssl_fc_sni", acl_parse_str, acl_match_str },
3129 { "ssl_fc_sni_end", "ssl_fc_sni", acl_parse_str, acl_match_end },
3130 { "ssl_fc_sni_reg", "ssl_fc_sni", acl_parse_reg, acl_match_reg },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01003131 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02003132}};
3133
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003134/* Note: must not be declared <const> as its list will be overwritten.
3135 * Please take care of keeping this list alphabetically sorted, doing so helps
3136 * all code contributors.
3137 * Optional keywords are also declared with a NULL ->parse() function so that
3138 * the config parser can report an appropriate error when a known keyword was
3139 * not enabled.
3140 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02003141static struct bind_kw_list bind_kws = { "SSL", { }, {
Willy Tarreauab861d32013-04-02 02:30:41 +02003142 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003143 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003144 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
3145 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003146 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003147 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
3148 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003149 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003150 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003151 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
3152 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
3153 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
3154 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02003155 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
3156 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
3157 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
3158 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003159 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003160 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003161 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003162 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003163 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003164 { NULL, NULL, 0 },
3165}};
Emeric Brun46591952012-05-18 15:47:34 +02003166
Willy Tarreau92faadf2012-10-10 23:04:25 +02003167/* Note: must not be declared <const> as its list will be overwritten.
3168 * Please take care of keeping this list alphabetically sorted, doing so helps
3169 * all code contributors.
3170 * Optional keywords are also declared with a NULL ->parse() function so that
3171 * the config parser can report an appropriate error when a known keyword was
3172 * not enabled.
3173 */
3174static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02003175 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003176 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
3177 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02003178 { "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 +02003179 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003180 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
3181 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
3182 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
3183 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
3184 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
3185 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
3186 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
3187 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02003188 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003189 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02003190 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Willy Tarreau92faadf2012-10-10 23:04:25 +02003191 { NULL, NULL, 0, 0 },
3192}};
3193
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003194/* transport-layer operations for SSL sockets */
3195struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02003196 .snd_buf = ssl_sock_from_buf,
3197 .rcv_buf = ssl_sock_to_buf,
3198 .rcv_pipe = NULL,
3199 .snd_pipe = NULL,
3200 .shutr = NULL,
3201 .shutw = ssl_sock_shutw,
3202 .close = ssl_sock_close,
3203 .init = ssl_sock_init,
3204};
3205
3206__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02003207static void __ssl_sock_init(void)
3208{
Emeric Brun46591952012-05-18 15:47:34 +02003209 STACK_OF(SSL_COMP)* cm;
3210
3211 SSL_library_init();
3212 cm = SSL_COMP_get_compression_methods();
3213 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02003214 sample_register_fetches(&sample_fetch_keywords);
3215 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003216 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02003217 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02003218}
3219
3220/*
3221 * Local variables:
3222 * c-indent-level: 8
3223 * c-basic-offset: 8
3224 * End:
3225 */