blob: e1e18c31b673078a5975dadd1ba59d21ed693437 [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. */
Evan Broderbe554312013-06-27 00:05:25 -0700107int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +0200108{
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 :
Emmanuel Hocdet79274e22013-05-31 12:47:44 +0200200 SSL_TLSEXT_ERR_NOACK);
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 }
222 if (!node && wildp) {
223 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +0200224 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200225 }
226 if (!node || container_of(node, struct sni_ctx, name)->neg) {
227 return (s->strict_sni ?
228 SSL_TLSEXT_ERR_ALERT_FATAL :
229 SSL_TLSEXT_ERR_ALERT_WARNING);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200230 }
231
232 /* switch ctx */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200233 SSL_set_SSL_CTX(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200234 return SSL_TLSEXT_ERR_OK;
235}
236#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
237
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200238#ifndef OPENSSL_NO_DH
239/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
240 if an error occured, and 0 if parameter not found. */
241int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
242{
243 int ret = -1;
244 BIO *in;
245 DH *dh = NULL;
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200246 /* If not present, use parameters generated using 'openssl dhparam 1024 -C':
247 * -----BEGIN DH PARAMETERS-----
248 * MIGHAoGBAJJAJDXDoS5E03MNjnjK36eOL1tRqVa/9NuOVlI+lpXmPjJQbP65EvKn
249 * fSLnG7VMhoCJO4KtG88zf393ltP7loGB2bofcDSr+x+XsxBM8yA/Zj6BmQt+CQ9s
250 * TF7hoOV+wXTT6ErZ5y5qx9pq6hLfKXwTGFT78hrE6HnCO7xgtPdTAgEC
251 * -----END DH PARAMETERS-----
252 */
253 static const unsigned char dh1024_p[] = {
254 0x92, 0x40, 0x24, 0x35, 0xC3, 0xA1, 0x2E, 0x44, 0xD3, 0x73, 0x0D, 0x8E,
255 0x78, 0xCA, 0xDF, 0xA7, 0x8E, 0x2F, 0x5B, 0x51, 0xA9, 0x56, 0xBF, 0xF4,
256 0xDB, 0x8E, 0x56, 0x52, 0x3E, 0x96, 0x95, 0xE6, 0x3E, 0x32, 0x50, 0x6C,
257 0xFE, 0xB9, 0x12, 0xF2, 0xA7, 0x7D, 0x22, 0xE7, 0x1B, 0xB5, 0x4C, 0x86,
258 0x80, 0x89, 0x3B, 0x82, 0xAD, 0x1B, 0xCF, 0x33, 0x7F, 0x7F, 0x77, 0x96,
259 0xD3, 0xFB, 0x96, 0x81, 0x81, 0xD9, 0xBA, 0x1F, 0x70, 0x34, 0xAB, 0xFB,
260 0x1F, 0x97, 0xB3, 0x10, 0x4C, 0xF3, 0x20, 0x3F, 0x66, 0x3E, 0x81, 0x99,
261 0x0B, 0x7E, 0x09, 0x0F, 0x6C, 0x4C, 0x5E, 0xE1, 0xA0, 0xE5, 0x7E, 0xC1,
262 0x74, 0xD3, 0xE8, 0x4A, 0xD9, 0xE7, 0x2E, 0x6A, 0xC7, 0xDA, 0x6A, 0xEA,
263 0x12, 0xDF, 0x29, 0x7C, 0x13, 0x18, 0x54, 0xFB, 0xF2, 0x1A, 0xC4, 0xE8,
264 0x79, 0xC2, 0x3B, 0xBC, 0x60, 0xB4, 0xF7, 0x53,
265 };
266 static const unsigned char dh1024_g[] = {
267 0x02,
268 };
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200269
270 in = BIO_new(BIO_s_file());
271 if (in == NULL)
272 goto end;
273
274 if (BIO_read_filename(in, file) <= 0)
275 goto end;
276
277 dh = PEM_read_bio_DHparams(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200278 if (!dh) {
279 /* Clear openssl global errors stack */
280 ERR_clear_error();
281
282 dh = DH_new();
283 if (dh == NULL)
284 goto end;
285
286 dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
287 if (dh->p == NULL)
288 goto end;
289
290 dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
291 if (dh->g == NULL)
292 goto end;
293
294 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200295 }
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200296 else
297 ret = 1;
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200298
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200299 SSL_CTX_set_tmp_dh(ctx, dh);
Emeric Brun644cde02012-12-14 11:21:13 +0100300
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200301end:
302 if (dh)
303 DH_free(dh);
304
305 if (in)
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200306 BIO_free(in);
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200307
308 return ret;
309}
310#endif
311
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200312static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100313{
314 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200315 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100316
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200317 if (*name == '!') {
318 neg = 1;
319 name++;
320 }
321 if (*name == '*') {
322 wild = 1;
323 name++;
324 }
325 /* !* filter is a nop */
326 if (neg && wild)
327 return order;
328 if (*name) {
329 int j, len;
330 len = strlen(name);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100331 sc = malloc(sizeof(struct sni_ctx) + len + 1);
332 for (j = 0; j < len; j++)
333 sc->name.key[j] = tolower(name[j]);
334 sc->name.key[len] = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100335 sc->ctx = ctx;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200336 sc->order = order++;
337 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100338 if (wild)
339 ebst_insert(&s->sni_w_ctx, &sc->name);
340 else
341 ebst_insert(&s->sni_ctx, &sc->name);
342 }
343 return order;
344}
345
Emeric Brunfc0421f2012-09-07 17:30:07 +0200346/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
347 * an early error happens and the caller must call SSL_CTX_free() by itelf.
348 */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200349static 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 +0200350{
351 BIO *in;
352 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200353 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200354 int ret = -1;
355 int order = 0;
356 X509_NAME *xname;
357 char *str;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200358#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
359 STACK_OF(GENERAL_NAME) *names;
360#endif
361
362 in = BIO_new(BIO_s_file());
363 if (in == NULL)
364 goto end;
365
366 if (BIO_read_filename(in, file) <= 0)
367 goto end;
368
369 x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
370 if (x == NULL)
371 goto end;
372
Emeric Brun50bcecc2013-04-22 13:05:23 +0200373 if (fcount) {
374 while (fcount--)
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200375 order = ssl_sock_add_cert_sni(ctx, s, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100376 }
377 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200378#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100379 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
380 if (names) {
381 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
382 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
383 if (name->type == GEN_DNS) {
384 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200385 order = ssl_sock_add_cert_sni(ctx, s, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100386 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200387 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200388 }
389 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100390 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200391 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200392#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100393 xname = X509_get_subject_name(x);
394 i = -1;
395 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
396 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
397 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200398 order = ssl_sock_add_cert_sni(ctx, s, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100399 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200400 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200401 }
402 }
403
404 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
405 if (!SSL_CTX_use_certificate(ctx, x))
406 goto end;
407
408 if (ctx->extra_certs != NULL) {
409 sk_X509_pop_free(ctx->extra_certs, X509_free);
410 ctx->extra_certs = NULL;
411 }
412
413 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata))) {
414 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
415 X509_free(ca);
416 goto end;
417 }
418 }
419
420 err = ERR_get_error();
421 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
422 /* we successfully reached the last cert in the file */
423 ret = 1;
424 }
425 ERR_clear_error();
426
427end:
428 if (x)
429 X509_free(x);
430
431 if (in)
432 BIO_free(in);
433
434 return ret;
435}
436
Emeric Brun50bcecc2013-04-22 13:05:23 +0200437static 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 +0200438{
439 int ret;
440 SSL_CTX *ctx;
441
442 ctx = SSL_CTX_new(SSLv23_server_method());
443 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200444 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
445 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200446 return 1;
447 }
448
449 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200450 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
451 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200452 SSL_CTX_free(ctx);
453 return 1;
454 }
455
Emeric Brun50bcecc2013-04-22 13:05:23 +0200456 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200457 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200458 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
459 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200460 if (ret < 0) /* serious error, must do that ourselves */
461 SSL_CTX_free(ctx);
462 return 1;
463 }
Emeric Brun61694ab2012-10-26 13:35:33 +0200464
465 if (SSL_CTX_check_private_key(ctx) <= 0) {
466 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
467 err && *err ? *err : "", path);
468 return 1;
469 }
470
Emeric Brunfc0421f2012-09-07 17:30:07 +0200471 /* we must not free the SSL_CTX anymore below, since it's already in
472 * the tree, so it will be discovered and cleaned in time.
473 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200474#ifndef OPENSSL_NO_DH
475 ret = ssl_sock_load_dh_params(ctx, path);
476 if (ret < 0) {
477 if (err)
478 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
479 *err ? *err : "", path);
480 return 1;
481 }
482#endif
483
Emeric Brunfc0421f2012-09-07 17:30:07 +0200484#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200485 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200486 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
487 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +0200488 return 1;
489 }
490#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200491 if (!bind_conf->default_ctx)
492 bind_conf->default_ctx = ctx;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200493
494 return 0;
495}
496
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200497int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200498{
499 struct dirent *de;
500 DIR *dir;
501 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +0100502 char *end;
503 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200504 int cfgerr = 0;
505
506 if (!(dir = opendir(path)))
Emeric Brun50bcecc2013-04-22 13:05:23 +0200507 return ssl_sock_load_cert_file(path, bind_conf, curproxy, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200508
509 /* strip trailing slashes, including first one */
510 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
511 *end = 0;
512
Emeric Brunfc0421f2012-09-07 17:30:07 +0200513 while ((de = readdir(dir))) {
Willy Tarreauee2663b2012-12-06 11:36:59 +0100514 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200515 if (stat(fp, &buf) != 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200516 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
517 err && *err ? *err : "", fp, strerror(errno));
Emeric Brunfc0421f2012-09-07 17:30:07 +0200518 cfgerr++;
519 continue;
520 }
521 if (!S_ISREG(buf.st_mode))
522 continue;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200523 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, curproxy, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200524 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200525 closedir(dir);
526 return cfgerr;
527}
528
Thierry Fournier383085f2013-01-24 14:15:43 +0100529/* Make sure openssl opens /dev/urandom before the chroot. The work is only
530 * done once. Zero is returned if the operation fails. No error is returned
531 * if the random is said as not implemented, because we expect that openssl
532 * will use another method once needed.
533 */
534static int ssl_initialize_random()
535{
536 unsigned char random;
537 static int random_initialized = 0;
538
539 if (!random_initialized && RAND_bytes(&random, 1) != 0)
540 random_initialized = 1;
541
542 return random_initialized;
543}
544
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100545int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
546{
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200547 char thisline[LINESIZE];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100548 FILE *f;
549 int linenum = 0;
550 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100551
Willy Tarreauad1731d2013-04-02 17:35:58 +0200552 if ((f = fopen(file, "r")) == NULL) {
553 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100554 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200555 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100556
557 while (fgets(thisline, sizeof(thisline), f) != NULL) {
558 int arg;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200559 int newarg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100560 char *end;
561 char *args[MAX_LINE_ARGS + 1];
562 char *line = thisline;
563
564 linenum++;
565 end = line + strlen(line);
566 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
567 /* Check if we reached the limit and the last char is not \n.
568 * Watch out for the last line without the terminating '\n'!
569 */
Willy Tarreauad1731d2013-04-02 17:35:58 +0200570 memprintf(err, "line %d too long in file '%s', limit is %d characters",
571 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100572 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200573 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100574 }
575
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100576 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200577 newarg = 1;
578 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100579 if (*line == '#' || *line == '\n' || *line == '\r') {
580 /* end of string, end of loop */
581 *line = 0;
582 break;
583 }
584 else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +0200585 newarg = 1;
586 *line = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100587 }
Emeric Brun50bcecc2013-04-22 13:05:23 +0200588 else if (newarg) {
589 if (arg == MAX_LINE_ARGS) {
590 memprintf(err, "too many args on line %d in file '%s'.",
591 linenum, file);
592 cfgerr = 1;
593 break;
594 }
595 newarg = 0;
596 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100597 }
Emeric Brun50bcecc2013-04-22 13:05:23 +0200598 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100599 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200600 if (cfgerr)
601 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200602
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100603 /* empty line */
Emeric Brun50bcecc2013-04-22 13:05:23 +0200604 if (!arg)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100605 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100606
Emeric Brun50bcecc2013-04-22 13:05:23 +0200607 cfgerr = ssl_sock_load_cert_file(args[0], bind_conf, curproxy, &args[1], arg-1, err);
Willy Tarreauad1731d2013-04-02 17:35:58 +0200608 if (cfgerr) {
609 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100610 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200611 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100612 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100613 fclose(f);
614 return cfgerr;
615}
616
Emeric Brunfc0421f2012-09-07 17:30:07 +0200617#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
618#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
619#endif
620
621#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
622#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
Willy Tarreau7d588ee2012-11-26 18:47:31 +0100623#define SSL_renegotiate_pending(arg) 0
Emeric Brunfc0421f2012-09-07 17:30:07 +0200624#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200625#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
626#define SSL_OP_SINGLE_ECDH_USE 0
627#endif
Emeric Brun2d0c4822012-10-02 13:45:20 +0200628#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
629#define SSL_OP_NO_TICKET 0
630#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200631#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
632#define SSL_OP_NO_COMPRESSION 0
633#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +0200634#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
635#define SSL_OP_NO_TLSv1_1 0
636#endif
637#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
638#define SSL_OP_NO_TLSv1_2 0
639#endif
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200640#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
641#define SSL_OP_SINGLE_DH_USE 0
642#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200643#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
644#define SSL_OP_SINGLE_ECDH_USE 0
645#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200646#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
647#define SSL_MODE_RELEASE_BUFFERS 0
648#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200649int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy *curproxy)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200650{
651 int cfgerr = 0;
652 int ssloptions =
653 SSL_OP_ALL | /* all known workarounds for bugs */
654 SSL_OP_NO_SSLv2 |
655 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200656 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +0200657 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +0200658 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
659 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200660 int sslmode =
661 SSL_MODE_ENABLE_PARTIAL_WRITE |
662 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
663 SSL_MODE_RELEASE_BUFFERS;
664
Thierry Fournier383085f2013-01-24 14:15:43 +0100665 /* Make sure openssl opens /dev/urandom before the chroot */
666 if (!ssl_initialize_random()) {
667 Alert("OpenSSL random data generator initialization failed.\n");
668 cfgerr++;
669 }
670
Emeric Brun89675492012-10-05 13:48:26 +0200671 if (bind_conf->ssl_options & BC_SSL_O_NO_SSLV3)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200672 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brun89675492012-10-05 13:48:26 +0200673 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV10)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200674 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun89675492012-10-05 13:48:26 +0200675 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV11)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200676 ssloptions |= SSL_OP_NO_TLSv1_1;
Emeric Brun89675492012-10-05 13:48:26 +0200677 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV12)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200678 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun89675492012-10-05 13:48:26 +0200679 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
Emeric Brun2d0c4822012-10-02 13:45:20 +0200680 ssloptions |= SSL_OP_NO_TICKET;
Emeric Brun2cb7ae52012-10-05 14:14:21 +0200681 if (bind_conf->ssl_options & BC_SSL_O_USE_SSLV3)
682 SSL_CTX_set_ssl_version(ctx, SSLv3_server_method());
683 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV10)
684 SSL_CTX_set_ssl_version(ctx, TLSv1_server_method());
685#if SSL_OP_NO_TLSv1_1
686 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV11)
687 SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method());
688#endif
689#if SSL_OP_NO_TLSv1_2
690 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV12)
691 SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method());
692#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200693
694 SSL_CTX_set_options(ctx, ssloptions);
695 SSL_CTX_set_mode(ctx, sslmode);
Evan Broderbe554312013-06-27 00:05:25 -0700696 SSL_CTX_set_verify(ctx, bind_conf->verify ? bind_conf->verify : SSL_VERIFY_NONE, ssl_sock_bind_verifycbk);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200697 if (bind_conf->verify & SSL_VERIFY_PEER) {
Emeric Brunfb510ea2012-10-05 12:00:26 +0200698 if (bind_conf->ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200699 /* load CAfile to verify */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200700 if (!SSL_CTX_load_verify_locations(ctx, bind_conf->ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200701 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200702 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200703 cfgerr++;
704 }
705 /* set CA names fo client cert request, function returns void */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200706 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(bind_conf->ca_file));
Emeric Brund94b3fe2012-09-20 18:23:56 +0200707 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200708#ifdef X509_V_FLAG_CRL_CHECK
Emeric Brunfb510ea2012-10-05 12:00:26 +0200709 if (bind_conf->crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200710 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
711
Emeric Brunfb510ea2012-10-05 12:00:26 +0200712 if (!store || !X509_STORE_load_locations(store, bind_conf->crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200713 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200714 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200715 cfgerr++;
716 }
Emeric Brun561e5742012-10-02 15:20:55 +0200717 else {
718 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
719 }
Emeric Brund94b3fe2012-09-20 18:23:56 +0200720 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200721#endif
Emeric Brun644cde02012-12-14 11:21:13 +0100722 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +0200723 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200724
Emeric Brun4f65bff2012-11-16 15:11:00 +0100725 if (global.tune.ssllifetime)
726 SSL_CTX_set_timeout(ctx, global.tune.ssllifetime);
727
Emeric Brunfc0421f2012-09-07 17:30:07 +0200728 shared_context_set_cache(ctx);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200729 if (bind_conf->ciphers &&
730 !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200731 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 +0200732 curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200733 cfgerr++;
734 }
735
736 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200737#ifdef OPENSSL_NPN_NEGOTIATED
738 if (bind_conf->npn_str)
739 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
740#endif
Willy Tarreauab861d32013-04-02 02:30:41 +0200741#ifdef OPENSSL_ALPN_NEGOTIATED
742 if (bind_conf->alpn_str)
743 SSL_CTX_set_alpn_advertised_cb(ctx, ssl_sock_advertise_alpn_protos, bind_conf);
744#endif
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200745
Emeric Brunfc0421f2012-09-07 17:30:07 +0200746#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
747 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200748 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200749#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200750#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emeric Brun6924ef82013-03-06 14:08:53 +0100751 {
Emeric Brun2b58d042012-09-20 17:10:03 +0200752 int i;
753 EC_KEY *ecdh;
754
Emeric Brun6924ef82013-03-06 14:08:53 +0100755 i = OBJ_sn2nid(bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE);
Emeric Brun2b58d042012-09-20 17:10:03 +0200756 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
757 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 +0100758 curproxy->id, bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE,
759 bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +0200760 cfgerr++;
761 }
762 else {
763 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
764 EC_KEY_free(ecdh);
765 }
766 }
767#endif
768
Emeric Brunfc0421f2012-09-07 17:30:07 +0200769 return cfgerr;
770}
771
Evan Broderbe554312013-06-27 00:05:25 -0700772static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
773{
774 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
775 size_t prefixlen, suffixlen;
776
777 /* Trivial case */
778 if (strcmp(pattern, hostname) == 0)
779 return 1;
780
Evan Broderbe554312013-06-27 00:05:25 -0700781 /* The rest of this logic is based on RFC 6125, section 6.4.3
782 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
783
Emeric Bruna848dae2013-10-08 11:27:28 +0200784 pattern_wildcard = NULL;
785 pattern_left_label_end = pattern;
786 while (*pattern_left_label_end != '.') {
787 switch (*pattern_left_label_end) {
788 case 0:
789 /* End of label not found */
790 return 0;
791 case '*':
792 /* If there is more than one wildcards */
793 if (pattern_wildcard)
794 return 0;
795 pattern_wildcard = pattern_left_label_end;
796 break;
797 }
798 pattern_left_label_end++;
799 }
800
801 /* If it's not trivial and there is no wildcard, it can't
802 * match */
803 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -0700804 return 0;
805
806 /* Make sure all labels match except the leftmost */
807 hostname_left_label_end = strchr(hostname, '.');
808 if (!hostname_left_label_end
809 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
810 return 0;
811
812 /* Make sure the leftmost label of the hostname is long enough
813 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +0200814 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -0700815 return 0;
816
817 /* Finally compare the string on either side of the
818 * wildcard */
819 prefixlen = pattern_wildcard - pattern;
820 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +0200821 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
822 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -0700823 return 0;
824
825 return 1;
826}
827
828static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
829{
830 SSL *ssl;
831 struct connection *conn;
832 char *servername;
833
834 int depth;
835 X509 *cert;
836 STACK_OF(GENERAL_NAME) *alt_names;
837 int i;
838 X509_NAME *cert_subject;
839 char *str;
840
841 if (ok == 0)
842 return ok;
843
844 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
845 conn = (struct connection *)SSL_get_app_data(ssl);
846
847 servername = objt_server(conn->target)->ssl_ctx.verify_host;
848
849 /* We only need to verify the CN on the actual server cert,
850 * not the indirect CAs */
851 depth = X509_STORE_CTX_get_error_depth(ctx);
852 if (depth != 0)
853 return ok;
854
855 /* At this point, the cert is *not* OK unless we can find a
856 * hostname match */
857 ok = 0;
858
859 cert = X509_STORE_CTX_get_current_cert(ctx);
860 /* It seems like this might happen if verify peer isn't set */
861 if (!cert)
862 return ok;
863
864 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
865 if (alt_names) {
866 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
867 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
868 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +0200869#if OPENSSL_VERSION_NUMBER < 0x00907000L
870 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
871#else
Evan Broderbe554312013-06-27 00:05:25 -0700872 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +0200873#endif
Evan Broderbe554312013-06-27 00:05:25 -0700874 ok = ssl_sock_srv_hostcheck(str, servername);
875 OPENSSL_free(str);
876 }
877 }
878 }
Emeric Brun4ad50a42013-09-17 15:19:54 +0200879 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -0700880 }
881
882 cert_subject = X509_get_subject_name(cert);
883 i = -1;
884 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
885 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
886 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
887 ok = ssl_sock_srv_hostcheck(str, servername);
888 OPENSSL_free(str);
889 }
890 }
891
892 return ok;
893}
894
Emeric Brun94324a42012-10-11 14:00:19 +0200895/* prepare ssl context from servers options. Returns an error count */
896int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
897{
898 int cfgerr = 0;
899 int options =
900 SSL_OP_ALL | /* all known workarounds for bugs */
901 SSL_OP_NO_SSLv2 |
902 SSL_OP_NO_COMPRESSION;
903 int mode =
904 SSL_MODE_ENABLE_PARTIAL_WRITE |
905 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
906 SSL_MODE_RELEASE_BUFFERS;
907
Thierry Fournier383085f2013-01-24 14:15:43 +0100908 /* Make sure openssl opens /dev/urandom before the chroot */
909 if (!ssl_initialize_random()) {
910 Alert("OpenSSL random data generator initialization failed.\n");
911 cfgerr++;
912 }
913
Emeric Brun94324a42012-10-11 14:00:19 +0200914 /* Initiate SSL context for current server */
915 srv->ssl_ctx.reused_sess = NULL;
916 if (srv->use_ssl)
917 srv->xprt = &ssl_sock;
918 if (srv->check.use_ssl)
Simon Horman66183002013-02-23 10:16:43 +0900919 srv->check_common.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +0200920
921 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
922 if (!srv->ssl_ctx.ctx) {
923 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
924 proxy_type_str(curproxy), curproxy->id,
925 srv->id);
926 cfgerr++;
927 return cfgerr;
928 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200929 if (srv->ssl_ctx.client_crt) {
930 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
931 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
932 proxy_type_str(curproxy), curproxy->id,
933 srv->id, srv->ssl_ctx.client_crt);
934 cfgerr++;
935 }
936 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
937 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
938 proxy_type_str(curproxy), curproxy->id,
939 srv->id, srv->ssl_ctx.client_crt);
940 cfgerr++;
941 }
942 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
943 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
944 proxy_type_str(curproxy), curproxy->id,
945 srv->id, srv->ssl_ctx.client_crt);
946 cfgerr++;
947 }
948 }
Emeric Brun94324a42012-10-11 14:00:19 +0200949
950 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
951 options |= SSL_OP_NO_SSLv3;
952 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
953 options |= SSL_OP_NO_TLSv1;
954 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
955 options |= SSL_OP_NO_TLSv1_1;
956 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
957 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200958 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
959 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200960 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
961 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
962 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
963 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
964#if SSL_OP_NO_TLSv1_1
965 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
966 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
967#endif
968#if SSL_OP_NO_TLSv1_2
969 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
970 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
971#endif
972
973 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
974 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Evan Broderbe554312013-06-27 00:05:25 -0700975 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
976 srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE,
977 srv->ssl_ctx.verify_host ? ssl_sock_srv_verifycbk : NULL);
Emeric Brunef42d922012-10-11 16:11:36 +0200978 if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
979 if (srv->ssl_ctx.ca_file) {
980 /* load CAfile to verify */
981 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
982 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
983 curproxy->id, srv->id,
984 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
985 cfgerr++;
986 }
987 }
988#ifdef X509_V_FLAG_CRL_CHECK
989 if (srv->ssl_ctx.crl_file) {
990 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
991
992 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
993 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
994 curproxy->id, srv->id,
995 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
996 cfgerr++;
997 }
998 else {
999 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
1000 }
1001 }
1002#endif
1003 }
1004
Emeric Brun4f65bff2012-11-16 15:11:00 +01001005 if (global.tune.ssllifetime)
1006 SSL_CTX_set_timeout(srv->ssl_ctx.ctx, global.tune.ssllifetime);
1007
Emeric Brun94324a42012-10-11 14:00:19 +02001008 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
1009 if (srv->ssl_ctx.ciphers &&
1010 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
1011 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
1012 curproxy->id, srv->id,
1013 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
1014 cfgerr++;
1015 }
1016
1017 return cfgerr;
1018}
1019
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001020/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02001021 * be NULL, in which case nothing is done. Returns the number of errors
1022 * encountered.
1023 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001024int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001025{
1026 struct ebmb_node *node;
1027 struct sni_ctx *sni;
1028 int err = 0;
1029
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001030 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001031 return 0;
1032
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001033 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001034 while (node) {
1035 sni = ebmb_entry(node, struct sni_ctx, name);
1036 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001037 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001038 node = ebmb_next(node);
1039 }
1040
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001041 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001042 while (node) {
1043 sni = ebmb_entry(node, struct sni_ctx, name);
1044 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001045 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001046 node = ebmb_next(node);
1047 }
1048 return err;
1049}
1050
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001051/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02001052 * be NULL, in which case nothing is done. The default_ctx is nullified too.
1053 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001054void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001055{
1056 struct ebmb_node *node, *back;
1057 struct sni_ctx *sni;
1058
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001059 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001060 return;
1061
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001062 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001063 while (node) {
1064 sni = ebmb_entry(node, struct sni_ctx, name);
1065 back = ebmb_next(node);
1066 ebmb_delete(node);
1067 if (!sni->order) /* only free the CTX on its first occurrence */
1068 SSL_CTX_free(sni->ctx);
1069 free(sni);
1070 node = back;
1071 }
1072
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001073 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001074 while (node) {
1075 sni = ebmb_entry(node, struct sni_ctx, name);
1076 back = ebmb_next(node);
1077 ebmb_delete(node);
1078 if (!sni->order) /* only free the CTX on its first occurrence */
1079 SSL_CTX_free(sni->ctx);
1080 free(sni);
1081 node = back;
1082 }
1083
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001084 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02001085}
1086
Emeric Brun46591952012-05-18 15:47:34 +02001087/*
1088 * This function is called if SSL * context is not yet allocated. The function
1089 * is designed to be called before any other data-layer operation and sets the
1090 * handshake flag on the connection. It is safe to call it multiple times.
1091 * It returns 0 on success and -1 in error case.
1092 */
1093static int ssl_sock_init(struct connection *conn)
1094{
1095 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001096 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001097 return 0;
1098
Willy Tarreau20879a02012-12-03 16:32:10 +01001099 if (global.maxsslconn && sslconns >= global.maxsslconn) {
1100 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02001101 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001102 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001103
Emeric Brun46591952012-05-18 15:47:34 +02001104 /* If it is in client mode initiate SSL session
1105 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001106 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001107 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001108 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001109 if (!conn->xprt_ctx) {
1110 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001111 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001112 }
Emeric Brun46591952012-05-18 15:47:34 +02001113
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001114 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001115 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1116 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001117
1118 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001119 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001120
Evan Broderbe554312013-06-27 00:05:25 -07001121 /* set connection pointer */
1122 SSL_set_app_data(conn->xprt_ctx, conn);
1123
Emeric Brun46591952012-05-18 15:47:34 +02001124 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001125 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001126
1127 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001128 return 0;
1129 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001130 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001131 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001132 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001133 if (!conn->xprt_ctx) {
1134 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001135 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001136 }
Emeric Brun46591952012-05-18 15:47:34 +02001137
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001138 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001139
1140 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001141 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001142
Emeric Brune1f38db2012-09-03 20:36:47 +02001143 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001144 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +02001145
Emeric Brun46591952012-05-18 15:47:34 +02001146 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001147 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001148
1149 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001150 return 0;
1151 }
1152 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01001153 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02001154 return -1;
1155}
1156
1157
1158/* This is the callback which is used when an SSL handshake is pending. It
1159 * updates the FD status if it wants some polling before being called again.
1160 * It returns 0 if it fails in a fatal way or needs to poll to go further,
1161 * otherwise it returns non-zero and removes itself from the connection's
1162 * flags (the bit is provided in <flag> by the caller).
1163 */
1164int ssl_sock_handshake(struct connection *conn, unsigned int flag)
1165{
1166 int ret;
1167
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001168 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001169 goto out_error;
1170
Emeric Brun674b7432012-11-08 19:21:55 +01001171 /* If we use SSL_do_handshake to process a reneg initiated by
1172 * the remote peer, it sometimes returns SSL_ERROR_SSL.
1173 * Usually SSL_write and SSL_read are used and process implicitly
1174 * the reneg handshake.
1175 * Here we use SSL_peek as a workaround for reneg.
1176 */
1177 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
1178 char c;
1179
1180 ret = SSL_peek(conn->xprt_ctx, &c, 1);
1181 if (ret <= 0) {
1182 /* handshake may have not been completed, let's find why */
1183 ret = SSL_get_error(conn->xprt_ctx, ret);
1184 if (ret == SSL_ERROR_WANT_WRITE) {
1185 /* SSL handshake needs to write, L4 connection may not be ready */
1186 __conn_sock_stop_recv(conn);
1187 __conn_sock_poll_send(conn);
1188 return 0;
1189 }
1190 else if (ret == SSL_ERROR_WANT_READ) {
1191 /* handshake may have been completed but we have
1192 * no more data to read.
1193 */
1194 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
1195 ret = 1;
1196 goto reneg_ok;
1197 }
1198 /* SSL handshake needs to read, L4 connection is ready */
1199 if (conn->flags & CO_FL_WAIT_L4_CONN)
1200 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1201 __conn_sock_stop_send(conn);
1202 __conn_sock_poll_recv(conn);
1203 return 0;
1204 }
1205 else if (ret == SSL_ERROR_SYSCALL) {
1206 /* if errno is null, then connection was successfully established */
1207 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1208 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001209 if (!conn->err_code) {
1210 if (!((SSL *)conn->xprt_ctx)->packet_length)
1211 if (!errno)
1212 conn->err_code = CO_ER_SSL_EMPTY;
1213 else
1214 conn->err_code = CO_ER_SSL_ABORT;
1215 else
1216 conn->err_code = CO_ER_SSL_HANDSHAKE;
1217 }
Emeric Brun674b7432012-11-08 19:21:55 +01001218 goto out_error;
1219 }
1220 else {
1221 /* Fail on all other handshake errors */
1222 /* Note: OpenSSL may leave unread bytes in the socket's
1223 * buffer, causing an RST to be emitted upon close() on
1224 * TCP sockets. We first try to drain possibly pending
1225 * data to avoid this as much as possible.
1226 */
Willy Tarreau2b57cb82013-06-10 19:56:38 +02001227 if (conn->ctrl && conn->ctrl->drain)
1228 conn->ctrl->drain(conn->t.sock.fd);
Willy Tarreau20879a02012-12-03 16:32:10 +01001229 if (!conn->err_code)
1230 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01001231 goto out_error;
1232 }
1233 }
1234 /* read some data: consider handshake completed */
1235 goto reneg_ok;
1236 }
1237
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001238 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001239 if (ret != 1) {
1240 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001241 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001242
1243 if (ret == SSL_ERROR_WANT_WRITE) {
1244 /* SSL handshake needs to write, L4 connection may not be ready */
1245 __conn_sock_stop_recv(conn);
1246 __conn_sock_poll_send(conn);
1247 return 0;
1248 }
1249 else if (ret == SSL_ERROR_WANT_READ) {
1250 /* SSL handshake needs to read, L4 connection is ready */
1251 if (conn->flags & CO_FL_WAIT_L4_CONN)
1252 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1253 __conn_sock_stop_send(conn);
1254 __conn_sock_poll_recv(conn);
1255 return 0;
1256 }
Willy Tarreau89230192012-09-28 20:22:13 +02001257 else if (ret == SSL_ERROR_SYSCALL) {
1258 /* if errno is null, then connection was successfully established */
1259 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1260 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001261
1262 if (!((SSL *)conn->xprt_ctx)->packet_length)
1263 if (!errno)
1264 conn->err_code = CO_ER_SSL_EMPTY;
1265 else
1266 conn->err_code = CO_ER_SSL_ABORT;
1267 else
1268 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +02001269 goto out_error;
1270 }
Emeric Brun46591952012-05-18 15:47:34 +02001271 else {
1272 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02001273 /* Note: OpenSSL may leave unread bytes in the socket's
1274 * buffer, causing an RST to be emitted upon close() on
1275 * TCP sockets. We first try to drain possibly pending
1276 * data to avoid this as much as possible.
1277 */
Willy Tarreau2b57cb82013-06-10 19:56:38 +02001278 if (conn->ctrl && conn->ctrl->drain)
1279 conn->ctrl->drain(conn->t.sock.fd);
Willy Tarreau20879a02012-12-03 16:32:10 +01001280 if (!conn->err_code)
1281 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001282 goto out_error;
1283 }
1284 }
1285
Emeric Brun674b7432012-11-08 19:21:55 +01001286reneg_ok:
1287
Emeric Brun46591952012-05-18 15:47:34 +02001288 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001289 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001290 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +02001291 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001292 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1293 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001294
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001295 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001296 }
1297 }
1298
1299 /* The connection is now established at both layers, it's time to leave */
1300 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1301 return 1;
1302
1303 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001304 /* Clear openssl global errors stack */
1305 ERR_clear_error();
1306
Emeric Brun9fa89732012-10-04 17:09:56 +02001307 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001308 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1309 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1310 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001311 }
1312
Emeric Brun46591952012-05-18 15:47:34 +02001313 /* Fail on all other handshake errors */
1314 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001315 if (!conn->err_code)
1316 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001317 return 0;
1318}
1319
1320/* Receive up to <count> bytes from connection <conn>'s socket and store them
1321 * into buffer <buf>. The caller must ensure that <count> is always smaller
1322 * than the buffer's size. Only one call to recv() is performed, unless the
1323 * buffer wraps, in which case a second call may be performed. The connection's
1324 * flags are updated with whatever special event is detected (error, read0,
1325 * empty). The caller is responsible for taking care of those events and
1326 * avoiding the call if inappropriate. The function does not call the
1327 * connection's polling update function, so the caller is responsible for this.
1328 */
1329static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1330{
1331 int ret, done = 0;
1332 int try = count;
1333
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001334 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001335 goto out_error;
1336
1337 if (conn->flags & CO_FL_HANDSHAKE)
1338 /* a handshake was requested */
1339 return 0;
1340
1341 /* compute the maximum block size we can read at once. */
1342 if (buffer_empty(buf)) {
1343 /* let's realign the buffer to optimize I/O */
1344 buf->p = buf->data;
1345 }
1346 else if (buf->data + buf->o < buf->p &&
1347 buf->p + buf->i < buf->data + buf->size) {
1348 /* remaining space wraps at the end, with a moving limit */
1349 if (try > buf->data + buf->size - (buf->p + buf->i))
1350 try = buf->data + buf->size - (buf->p + buf->i);
1351 }
1352
1353 /* read the largest possible block. For this, we perform only one call
1354 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1355 * in which case we accept to do it once again. A new attempt is made on
1356 * EINTR too.
1357 */
1358 while (try) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001359 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001360 if (conn->flags & CO_FL_ERROR) {
1361 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001362 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001363 }
Emeric Brun46591952012-05-18 15:47:34 +02001364 if (ret > 0) {
1365 buf->i += ret;
1366 done += ret;
1367 if (ret < try)
1368 break;
1369 count -= ret;
1370 try = count;
1371 }
1372 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001373 ret = SSL_get_error(conn->xprt_ctx, ret);
1374 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001375 /* error on protocol or underlying transport */
1376 if ((ret != SSL_ERROR_SYSCALL)
1377 || (errno && (errno != EAGAIN)))
1378 conn->flags |= CO_FL_ERROR;
1379
Emeric Brun644cde02012-12-14 11:21:13 +01001380 /* Clear openssl global errors stack */
1381 ERR_clear_error();
1382 }
Emeric Brun46591952012-05-18 15:47:34 +02001383 goto read0;
1384 }
1385 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001386 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001387 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001388 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001389 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001390 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001391 break;
1392 }
1393 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001394 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1395 /* handshake is running, and it may need to re-enable read */
1396 conn->flags |= CO_FL_SSL_WAIT_HS;
1397 __conn_sock_want_recv(conn);
1398 break;
1399 }
Emeric Brun46591952012-05-18 15:47:34 +02001400 /* we need to poll for retry a read later */
1401 __conn_data_poll_recv(conn);
1402 break;
1403 }
1404 /* otherwise it's a real error */
1405 goto out_error;
1406 }
1407 }
1408 return done;
1409
1410 read0:
1411 conn_sock_read0(conn);
1412 return done;
1413 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001414 /* Clear openssl global errors stack */
1415 ERR_clear_error();
1416
Emeric Brun46591952012-05-18 15:47:34 +02001417 conn->flags |= CO_FL_ERROR;
1418 return done;
1419}
1420
1421
1422/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1423 * <flags> may contain MSG_MORE to make the system hold on without sending
1424 * data too fast, but this flag is ignored at the moment.
1425 * Only one call to send() is performed, unless the buffer wraps, in which case
1426 * a second call may be performed. The connection's flags are updated with
1427 * whatever special event is detected (error, empty). The caller is responsible
1428 * for taking care of those events and avoiding the call if inappropriate. The
1429 * function does not call the connection's polling update function, so the caller
1430 * is responsible for this.
1431 */
1432static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1433{
1434 int ret, try, done;
1435
1436 done = 0;
1437
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001438 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001439 goto out_error;
1440
1441 if (conn->flags & CO_FL_HANDSHAKE)
1442 /* a handshake was requested */
1443 return 0;
1444
1445 /* send the largest possible block. For this we perform only one call
1446 * to send() unless the buffer wraps and we exactly fill the first hunk,
1447 * in which case we accept to do it once again.
1448 */
1449 while (buf->o) {
Kevin Hestercad82342013-05-30 15:12:41 -07001450 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01001451
1452 if (global.tune.ssl_max_record && try > global.tune.ssl_max_record)
1453 try = global.tune.ssl_max_record;
1454
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001455 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001456 if (conn->flags & CO_FL_ERROR) {
1457 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001458 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001459 }
Emeric Brun46591952012-05-18 15:47:34 +02001460 if (ret > 0) {
1461 buf->o -= ret;
1462 done += ret;
1463
Willy Tarreau5fb38032012-12-16 19:39:09 +01001464 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001465 /* optimize data alignment in the buffer */
1466 buf->p = buf->data;
1467
1468 /* if the system buffer is full, don't insist */
1469 if (ret < try)
1470 break;
1471 }
1472 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001473 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001474 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001475 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1476 /* handshake is running, and it may need to re-enable write */
1477 conn->flags |= CO_FL_SSL_WAIT_HS;
1478 __conn_sock_want_send(conn);
1479 break;
1480 }
Emeric Brun46591952012-05-18 15:47:34 +02001481 /* we need to poll to retry a write later */
1482 __conn_data_poll_send(conn);
1483 break;
1484 }
1485 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001486 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001487 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001488 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001489 break;
1490 }
1491 goto out_error;
1492 }
1493 }
1494 return done;
1495
1496 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001497 /* Clear openssl global errors stack */
1498 ERR_clear_error();
1499
Emeric Brun46591952012-05-18 15:47:34 +02001500 conn->flags |= CO_FL_ERROR;
1501 return done;
1502}
1503
Emeric Brun46591952012-05-18 15:47:34 +02001504static void ssl_sock_close(struct connection *conn) {
1505
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001506 if (conn->xprt_ctx) {
1507 SSL_free(conn->xprt_ctx);
1508 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001509 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001510 }
Emeric Brun46591952012-05-18 15:47:34 +02001511}
1512
1513/* This function tries to perform a clean shutdown on an SSL connection, and in
1514 * any case, flags the connection as reusable if no handshake was in progress.
1515 */
1516static void ssl_sock_shutw(struct connection *conn, int clean)
1517{
1518 if (conn->flags & CO_FL_HANDSHAKE)
1519 return;
1520 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001521 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1522 /* Clear openssl global errors stack */
1523 ERR_clear_error();
1524 }
Emeric Brun46591952012-05-18 15:47:34 +02001525
1526 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001527 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001528}
1529
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001530/* used for logging, may be changed for a sample fetch later */
1531const char *ssl_sock_get_cipher_name(struct connection *conn)
1532{
1533 if (!conn->xprt && !conn->xprt_ctx)
1534 return NULL;
1535 return SSL_get_cipher_name(conn->xprt_ctx);
1536}
1537
1538/* used for logging, may be changed for a sample fetch later */
1539const char *ssl_sock_get_proto_version(struct connection *conn)
1540{
1541 if (!conn->xprt && !conn->xprt_ctx)
1542 return NULL;
1543 return SSL_get_version(conn->xprt_ctx);
1544}
1545
Willy Tarreau8d598402012-10-22 17:58:39 +02001546/* Extract a serial from a cert, and copy it to a chunk.
1547 * Returns 1 if serial is found and copied, 0 if no serial found and
1548 * -1 if output is not large enough.
1549 */
1550static int
1551ssl_sock_get_serial(X509 *crt, struct chunk *out)
1552{
1553 ASN1_INTEGER *serial;
1554
1555 serial = X509_get_serialNumber(crt);
1556 if (!serial)
1557 return 0;
1558
1559 if (out->size < serial->length)
1560 return -1;
1561
1562 memcpy(out->str, serial->data, serial->length);
1563 out->len = serial->length;
1564 return 1;
1565}
1566
Emeric Brunce5ad802012-10-22 14:11:22 +02001567
1568/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1569 * Returns 1 if serial is found and copied, 0 if no valid time found
1570 * and -1 if output is not large enough.
1571 */
1572static int
1573ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1574{
1575 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1576 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1577
1578 if (gentm->length < 12)
1579 return 0;
1580 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1581 return 0;
1582 if (out->size < gentm->length-2)
1583 return -1;
1584
1585 memcpy(out->str, gentm->data+2, gentm->length-2);
1586 out->len = gentm->length-2;
1587 return 1;
1588 }
1589 else if (tm->type == V_ASN1_UTCTIME) {
1590 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1591
1592 if (utctm->length < 10)
1593 return 0;
1594 if (utctm->data[0] >= 0x35)
1595 return 0;
1596 if (out->size < utctm->length)
1597 return -1;
1598
1599 memcpy(out->str, utctm->data, utctm->length);
1600 out->len = utctm->length;
1601 return 1;
1602 }
1603
1604 return 0;
1605}
1606
Emeric Brun87855892012-10-17 17:39:35 +02001607/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1608 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1609 */
1610static int
1611ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1612{
1613 X509_NAME_ENTRY *ne;
1614 int i, j, n;
1615 int cur = 0;
1616 const char *s;
1617 char tmp[128];
1618
1619 out->len = 0;
1620 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1621 if (pos < 0)
1622 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1623 else
1624 j = i;
1625
1626 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1627 n = OBJ_obj2nid(ne->object);
1628 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1629 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1630 s = tmp;
1631 }
1632
1633 if (chunk_strcasecmp(entry, s) != 0)
1634 continue;
1635
1636 if (pos < 0)
1637 cur--;
1638 else
1639 cur++;
1640
1641 if (cur != pos)
1642 continue;
1643
1644 if (ne->value->length > out->size)
1645 return -1;
1646
1647 memcpy(out->str, ne->value->data, ne->value->length);
1648 out->len = ne->value->length;
1649 return 1;
1650 }
1651
1652 return 0;
1653
1654}
1655
1656/* Extract and format full DN from a X509_NAME and copy result into a chunk
1657 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1658 */
1659static int
1660ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1661{
1662 X509_NAME_ENTRY *ne;
1663 int i, n, ln;
1664 int l = 0;
1665 const char *s;
1666 char *p;
1667 char tmp[128];
1668
1669 out->len = 0;
1670 p = out->str;
1671 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1672 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1673 n = OBJ_obj2nid(ne->object);
1674 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1675 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1676 s = tmp;
1677 }
1678 ln = strlen(s);
1679
1680 l += 1 + ln + 1 + ne->value->length;
1681 if (l > out->size)
1682 return -1;
1683 out->len = l;
1684
1685 *(p++)='/';
1686 memcpy(p, s, ln);
1687 p += ln;
1688 *(p++)='=';
1689 memcpy(p, ne->value->data, ne->value->length);
1690 p += ne->value->length;
1691 }
1692
1693 if (!out->len)
1694 return 0;
1695
1696 return 1;
1697}
1698
Willy Tarreau7875d092012-09-10 08:20:03 +02001699/***** Below are some sample fetching functions for ACL/patterns *****/
1700
Emeric Brune64aef12012-09-21 13:15:06 +02001701/* boolean, returns true if client cert was present */
1702static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001703smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001704 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brune64aef12012-09-21 13:15:06 +02001705{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001706 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001707 return 0;
1708
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001709 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001710 smp->flags |= SMP_F_MAY_CHANGE;
1711 return 0;
1712 }
1713
1714 smp->flags = 0;
1715 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001716 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001717
1718 return 1;
1719}
1720
Willy Tarreau8d598402012-10-22 17:58:39 +02001721/* bin, returns serial in a binary chunk */
1722static int
1723smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001724 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02001725{
1726 X509 *crt = NULL;
1727 int ret = 0;
1728 struct chunk *smp_trash;
1729
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001730 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001731 return 0;
1732
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001733 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001734 smp->flags |= SMP_F_MAY_CHANGE;
1735 return 0;
1736 }
1737
1738 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001739 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001740 if (!crt)
1741 goto out;
1742
Willy Tarreau47ca5452012-12-23 20:22:19 +01001743 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001744 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1745 goto out;
1746
1747 smp->data.str = *smp_trash;
1748 smp->type = SMP_T_BIN;
1749 ret = 1;
1750out:
1751 if (crt)
1752 X509_free(crt);
1753 return ret;
1754}
Emeric Brune64aef12012-09-21 13:15:06 +02001755
James Votha051b4a2013-05-14 20:37:59 +02001756/* bin, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk */
1757static int
1758smp_fetch_ssl_c_sha1(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001759 const struct arg *args, struct sample *smp, const char *kw)
James Votha051b4a2013-05-14 20:37:59 +02001760{
1761 X509 *crt = NULL;
1762 const EVP_MD *digest;
1763 int ret = 0;
1764 struct chunk *smp_trash;
1765
1766 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
1767 return 0;
1768
1769 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
1770 smp->flags |= SMP_F_MAY_CHANGE;
1771 return 0;
1772 }
1773
1774 /* SSL_get_peer_certificate, it increase X509 * ref count */
1775 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
1776 if (!crt)
1777 goto out;
1778
1779 smp_trash = get_trash_chunk();
1780 digest = EVP_sha1();
1781 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
1782
1783 smp->data.str = *smp_trash;
1784 smp->type = SMP_T_BIN;
1785 ret = 1;
1786out:
1787 if (crt)
1788 X509_free(crt);
1789 return ret;
1790}
1791
Emeric Brunce5ad802012-10-22 14:11:22 +02001792/*str, returns notafter date in ASN1_UTCTIME format */
1793static int
1794smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001795 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001796{
1797 X509 *crt = NULL;
1798 int ret = 0;
1799 struct chunk *smp_trash;
1800
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001801 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001802 return 0;
1803
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001804 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001805 smp->flags |= SMP_F_MAY_CHANGE;
1806 return 0;
1807 }
1808
1809 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001810 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001811 if (!crt)
1812 goto out;
1813
Willy Tarreau47ca5452012-12-23 20:22:19 +01001814 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001815 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1816 goto out;
1817
1818 smp->data.str = *smp_trash;
1819 smp->type = SMP_T_STR;
1820 ret = 1;
1821out:
1822 if (crt)
1823 X509_free(crt);
1824 return ret;
1825}
1826
Emeric Brun87855892012-10-17 17:39:35 +02001827/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1828static int
1829smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001830 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02001831{
1832 X509 *crt = NULL;
1833 X509_NAME *name;
1834 int ret = 0;
1835 struct chunk *smp_trash;
1836
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001837 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001838 return 0;
1839
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001840 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001841 smp->flags |= SMP_F_MAY_CHANGE;
1842 return 0;
1843 }
1844
1845 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001846 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001847 if (!crt)
1848 goto out;
1849
1850 name = X509_get_issuer_name(crt);
1851 if (!name)
1852 goto out;
1853
Willy Tarreau47ca5452012-12-23 20:22:19 +01001854 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001855 if (args && args[0].type == ARGT_STR) {
1856 int pos = 1;
1857
1858 if (args[1].type == ARGT_SINT)
1859 pos = args[1].data.sint;
1860 else if (args[1].type == ARGT_UINT)
1861 pos =(int)args[1].data.uint;
1862
1863 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1864 goto out;
1865 }
1866 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1867 goto out;
1868
1869 smp->type = SMP_T_STR;
1870 smp->data.str = *smp_trash;
1871 ret = 1;
1872out:
1873 if (crt)
1874 X509_free(crt);
1875 return ret;
1876}
1877
Emeric Brunce5ad802012-10-22 14:11:22 +02001878/*str, returns notbefore date in ASN1_UTCTIME format */
1879static int
1880smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001881 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001882{
1883 X509 *crt = NULL;
1884 int ret = 0;
1885 struct chunk *smp_trash;
1886
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001887 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001888 return 0;
1889
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001890 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001891 smp->flags |= SMP_F_MAY_CHANGE;
1892 return 0;
1893 }
1894
1895 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001896 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001897 if (!crt)
1898 goto out;
1899
Willy Tarreau47ca5452012-12-23 20:22:19 +01001900 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001901 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1902 goto out;
1903
1904 smp->data.str = *smp_trash;
1905 smp->type = SMP_T_STR;
1906 ret = 1;
1907out:
1908 if (crt)
1909 X509_free(crt);
1910 return ret;
1911}
1912
Emeric Brun87855892012-10-17 17:39:35 +02001913/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1914static int
1915smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001916 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02001917{
1918 X509 *crt = NULL;
1919 X509_NAME *name;
1920 int ret = 0;
1921 struct chunk *smp_trash;
1922
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001923 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001924 return 0;
1925
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001926 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001927 smp->flags |= SMP_F_MAY_CHANGE;
1928 return 0;
1929 }
1930
1931 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001932 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001933 if (!crt)
1934 goto out;
1935
1936 name = X509_get_subject_name(crt);
1937 if (!name)
1938 goto out;
1939
Willy Tarreau47ca5452012-12-23 20:22:19 +01001940 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001941 if (args && args[0].type == ARGT_STR) {
1942 int pos = 1;
1943
1944 if (args[1].type == ARGT_SINT)
1945 pos = args[1].data.sint;
1946 else if (args[1].type == ARGT_UINT)
1947 pos =(int)args[1].data.uint;
1948
1949 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1950 goto out;
1951 }
1952 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1953 goto out;
1954
1955 smp->type = SMP_T_STR;
1956 smp->data.str = *smp_trash;
1957 ret = 1;
1958out:
1959 if (crt)
1960 X509_free(crt);
1961 return ret;
1962}
Emeric Brun9143d372012-12-20 15:44:16 +01001963
1964/* integer, returns true if current session use a client certificate */
1965static int
1966smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001967 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun9143d372012-12-20 15:44:16 +01001968{
1969 X509 *crt;
1970
1971 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
1972 return 0;
1973
1974 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
1975 smp->flags |= SMP_F_MAY_CHANGE;
1976 return 0;
1977 }
1978
1979 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
1980 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
1981 if (crt) {
1982 X509_free(crt);
1983 }
1984
1985 smp->type = SMP_T_BOOL;
1986 smp->data.uint = (crt != NULL);
1987 return 1;
1988}
1989
Emeric Bruna7359fd2012-10-17 15:03:11 +02001990/* integer, returns the client certificate version */
1991static int
1992smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001993 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001994{
1995 X509 *crt;
1996
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001997 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001998 return 0;
1999
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002000 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002001 smp->flags |= SMP_F_MAY_CHANGE;
2002 return 0;
2003 }
2004
2005 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002006 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002007 if (!crt)
2008 return 0;
2009
2010 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2011 X509_free(crt);
2012 smp->type = SMP_T_UINT;
2013
2014 return 1;
2015}
2016
Emeric Brun7f56e742012-10-19 18:15:40 +02002017/* str, returns the client certificate sig alg */
2018static int
2019smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002020 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002021{
2022 X509 *crt;
2023 int nid;
2024
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002025 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02002026 return 0;
2027
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002028 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002029 smp->flags |= SMP_F_MAY_CHANGE;
2030 return 0;
2031 }
2032
2033 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002034 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002035 if (!crt)
2036 return 0;
2037
2038 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2039
2040 smp->data.str.str = (char *)OBJ_nid2sn(nid);
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002041 if (!smp->data.str.str) {
2042 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02002043 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002044 }
Emeric Brun7f56e742012-10-19 18:15:40 +02002045
2046 smp->type = SMP_T_CSTR;
2047 smp->data.str.len = strlen(smp->data.str.str);
2048 X509_free(crt);
2049
2050 return 1;
2051}
2052
Emeric Brun521a0112012-10-22 12:22:55 +02002053/* str, returns the client certificate key alg */
2054static int
2055smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002056 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002057{
2058 X509 *crt;
2059 int nid;
2060
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002061 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002062 return 0;
2063
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002064 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002065 smp->flags |= SMP_F_MAY_CHANGE;
2066 return 0;
2067 }
2068
2069 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002070 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002071 if (!crt)
2072 return 0;
2073
2074 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2075
2076 smp->data.str.str = (char *)OBJ_nid2sn(nid);
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002077 if (!smp->data.str.str) {
2078 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02002079 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002080 }
Emeric Brun521a0112012-10-22 12:22:55 +02002081
2082 smp->type = SMP_T_CSTR;
2083 smp->data.str.len = strlen(smp->data.str.str);
2084 X509_free(crt);
2085
2086 return 1;
2087}
2088
Emeric Brun2525b6b2012-10-18 15:59:43 +02002089/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02002090static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002091smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002092 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002093{
2094 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002095 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02002096 return 1;
2097}
2098
Emeric Brun2525b6b2012-10-18 15:59:43 +02002099/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02002100static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002101smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002102 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002103{
2104#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2105 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002106 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock) &&
2107 l4->si[0].conn->xprt_ctx &&
2108 SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02002109 return 1;
2110#else
2111 return 0;
2112#endif
2113}
2114
Willy Tarreau8d598402012-10-22 17:58:39 +02002115/* bin, returns serial in a binary chunk */
2116static int
2117smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002118 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02002119{
2120 X509 *crt = NULL;
2121 int ret = 0;
2122 struct chunk *smp_trash;
2123
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002124 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02002125 return 0;
2126
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002127 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02002128 smp->flags |= SMP_F_MAY_CHANGE;
2129 return 0;
2130 }
2131
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002132 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02002133 if (!crt)
2134 goto out;
2135
Willy Tarreau47ca5452012-12-23 20:22:19 +01002136 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02002137 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
2138 goto out;
2139
2140 smp->data.str = *smp_trash;
2141 smp->type = SMP_T_BIN;
2142 ret = 1;
2143out:
2144 return ret;
2145}
Emeric Brunce5ad802012-10-22 14:11:22 +02002146/*str, returns notafter date in ASN1_UTCTIME format */
2147static int
2148smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002149 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002150{
2151 X509 *crt = NULL;
2152 int ret = 0;
2153 struct chunk *smp_trash;
2154
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002155 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02002156 return 0;
2157
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002158 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002159 smp->flags |= SMP_F_MAY_CHANGE;
2160 return 0;
2161 }
2162
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002163 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002164 if (!crt)
2165 goto out;
2166
Willy Tarreau47ca5452012-12-23 20:22:19 +01002167 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002168 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
2169 goto out;
2170
2171 smp->data.str = *smp_trash;
2172 smp->type = SMP_T_STR;
2173 ret = 1;
2174out:
2175 return ret;
2176}
2177
2178/*str, returns notbefore date in ASN1_UTCTIME format */
2179static int
2180smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002181 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002182{
2183 X509 *crt = NULL;
2184 int ret = 0;
2185 struct chunk *smp_trash;
2186
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002187 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02002188 return 0;
2189
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002190 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002191 smp->flags |= SMP_F_MAY_CHANGE;
2192 return 0;
2193 }
2194
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002195 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002196 if (!crt)
2197 goto out;
2198
Willy Tarreau47ca5452012-12-23 20:22:19 +01002199 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002200 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
2201 goto out;
2202
2203 smp->data.str = *smp_trash;
2204 smp->type = SMP_T_STR;
2205 ret = 1;
2206out:
2207 return ret;
2208}
Willy Tarreau8d598402012-10-22 17:58:39 +02002209
Emeric Bruna7359fd2012-10-17 15:03:11 +02002210/* integer, returns the frontend certificate version */
2211static int
2212smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002213 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002214{
2215 X509 *crt;
2216
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002217 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002218 return 0;
2219
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002220 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002221 smp->flags |= SMP_F_MAY_CHANGE;
2222 return 0;
2223 }
2224
2225 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002226 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002227 if (!crt)
2228 return 0;
2229
2230 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2231 smp->type = SMP_T_UINT;
2232
2233 return 1;
2234}
2235
Emeric Brun7f56e742012-10-19 18:15:40 +02002236/* str, returns the client certificate sig alg */
2237static int
2238smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002239 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002240{
2241 X509 *crt;
2242 int nid;
2243
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002244 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02002245 return 0;
2246
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002247 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002248 smp->flags |= SMP_F_MAY_CHANGE;
2249 return 0;
2250 }
2251
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002252 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002253 if (!crt)
2254 return 0;
2255
2256 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2257
2258 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2259 if (!smp->data.str.str)
2260 return 0;
2261
2262 smp->type = SMP_T_CSTR;
2263 smp->data.str.len = strlen(smp->data.str.str);
2264
2265 return 1;
2266}
2267
Emeric Brun521a0112012-10-22 12:22:55 +02002268/* str, returns the client certificate key alg */
2269static int
2270smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002271 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002272{
2273 X509 *crt;
2274 int nid;
2275
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002276 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002277 return 0;
2278
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002279 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002280 smp->flags |= SMP_F_MAY_CHANGE;
2281 return 0;
2282 }
2283
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002284 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002285 if (!crt)
2286 return 0;
2287
2288 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2289
2290 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2291 if (!smp->data.str.str)
2292 return 0;
2293
2294 smp->type = SMP_T_CSTR;
2295 smp->data.str.len = strlen(smp->data.str.str);
2296
2297 return 1;
2298}
2299
Emeric Brun87855892012-10-17 17:39:35 +02002300/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2301static int
2302smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002303 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002304{
2305 X509 *crt = NULL;
2306 X509_NAME *name;
2307 int ret = 0;
2308 struct chunk *smp_trash;
2309
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002310 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002311 return 0;
2312
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002313 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002314 smp->flags |= SMP_F_MAY_CHANGE;
2315 return 0;
2316 }
2317
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002318 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002319 if (!crt)
2320 goto out;
2321
2322 name = X509_get_issuer_name(crt);
2323 if (!name)
2324 goto out;
2325
Willy Tarreau47ca5452012-12-23 20:22:19 +01002326 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002327 if (args && args[0].type == ARGT_STR) {
2328 int pos = 1;
2329
2330 if (args[1].type == ARGT_SINT)
2331 pos = args[1].data.sint;
2332 else if (args[1].type == ARGT_UINT)
2333 pos =(int)args[1].data.uint;
2334
2335 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2336 goto out;
2337 }
2338 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2339 goto out;
2340
2341 smp->type = SMP_T_STR;
2342 smp->data.str = *smp_trash;
2343 ret = 1;
2344out:
2345 return ret;
2346}
2347
2348/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2349static int
2350smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002351 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002352{
2353 X509 *crt = NULL;
2354 X509_NAME *name;
2355 int ret = 0;
2356 struct chunk *smp_trash;
2357
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002358 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002359 return 0;
2360
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002361 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002362 smp->flags |= SMP_F_MAY_CHANGE;
2363 return 0;
2364 }
2365
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002366 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002367 if (!crt)
2368 goto out;
2369
2370 name = X509_get_subject_name(crt);
2371 if (!name)
2372 goto out;
2373
Willy Tarreau47ca5452012-12-23 20:22:19 +01002374 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002375 if (args && args[0].type == ARGT_STR) {
2376 int pos = 1;
2377
2378 if (args[1].type == ARGT_SINT)
2379 pos = args[1].data.sint;
2380 else if (args[1].type == ARGT_UINT)
2381 pos =(int)args[1].data.uint;
2382
2383 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2384 goto out;
2385 }
2386 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2387 goto out;
2388
2389 smp->type = SMP_T_STR;
2390 smp->data.str = *smp_trash;
2391 ret = 1;
2392out:
2393 return ret;
2394}
2395
Emeric Brun589fcad2012-10-16 14:13:26 +02002396static int
2397smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002398 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002399{
2400 smp->flags = 0;
2401
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002402 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002403 return 0;
2404
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002405 smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002406 if (!smp->data.str.str)
2407 return 0;
2408
2409 smp->type = SMP_T_CSTR;
2410 smp->data.str.len = strlen(smp->data.str.str);
2411
2412 return 1;
2413}
2414
2415static int
2416smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002417 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002418{
2419 smp->flags = 0;
2420
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002421 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002422 return 0;
2423
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002424 if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
Emeric Brun589fcad2012-10-16 14:13:26 +02002425 return 0;
2426
2427 smp->type = SMP_T_UINT;
2428
2429 return 1;
2430}
2431
2432static int
2433smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002434 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002435{
2436 smp->flags = 0;
2437
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002438 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002439 return 0;
2440
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002441 smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002442 if (!smp->data.uint)
2443 return 0;
2444
2445 smp->type = SMP_T_UINT;
2446
2447 return 1;
2448}
2449
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002450#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002451static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002452smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002453 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002454{
Willy Tarreaua33c6542012-10-15 13:19:06 +02002455 smp->flags = 0;
2456 smp->type = SMP_T_CSTR;
2457
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002458 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002459 return 0;
2460
2461 smp->data.str.str = NULL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002462 SSL_get0_next_proto_negotiated(l4->si[0].conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002463 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2464
2465 if (!smp->data.str.str)
2466 return 0;
2467
2468 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002469}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002470#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002471
Willy Tarreauab861d32013-04-02 02:30:41 +02002472#ifdef OPENSSL_ALPN_NEGOTIATED
2473static int
2474smp_fetch_ssl_fc_alpn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002475 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreauab861d32013-04-02 02:30:41 +02002476{
2477 smp->flags = 0;
2478 smp->type = SMP_T_CSTR;
2479
2480 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
2481 return 0;
2482
2483 smp->data.str.str = NULL;
2484 SSL_get0_alpn_negotiated(l4->si[0].conn->xprt_ctx,
2485 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2486
2487 if (!smp->data.str.str)
2488 return 0;
2489
2490 return 1;
2491}
2492#endif
2493
Willy Tarreaua33c6542012-10-15 13:19:06 +02002494static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002495smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002496 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002497{
2498 smp->flags = 0;
2499
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002500 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002501 return 0;
2502
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002503 smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002504 if (!smp->data.str.str)
2505 return 0;
2506
2507 smp->type = SMP_T_CSTR;
2508 smp->data.str.len = strlen(smp->data.str.str);
2509
2510 return 1;
2511}
2512
2513static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002514smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002515 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunfe68f682012-10-16 14:59:28 +02002516{
2517#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2518 SSL_SESSION *sess;
2519
2520 smp->flags = 0;
2521 smp->type = SMP_T_CBIN;
2522
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002523 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunfe68f682012-10-16 14:59:28 +02002524 return 0;
2525
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002526 sess = SSL_get_session(l4->si[0].conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002527 if (!sess)
2528 return 0;
2529
2530 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2531 if (!smp->data.str.str || !&smp->data.str.len)
2532 return 0;
2533
2534 return 1;
2535#else
2536 return 0;
2537#endif
2538}
2539
2540static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002541smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002542 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002543{
2544#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2545 smp->flags = 0;
2546 smp->type = SMP_T_CSTR;
2547
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002548 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau7875d092012-09-10 08:20:03 +02002549 return 0;
2550
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002551 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 +02002552 if (!smp->data.str.str)
2553 return 0;
2554
Willy Tarreau7875d092012-09-10 08:20:03 +02002555 smp->data.str.len = strlen(smp->data.str.str);
2556 return 1;
2557#else
2558 return 0;
2559#endif
2560}
2561
Emeric Brun2525b6b2012-10-18 15:59:43 +02002562/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002563static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002564smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002565 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002566{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002567 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002568 return 0;
2569
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002570 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002571 smp->flags = SMP_F_MAY_CHANGE;
2572 return 0;
2573 }
2574
2575 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002576 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002577 smp->flags = 0;
2578
2579 return 1;
2580}
2581
Emeric Brun2525b6b2012-10-18 15:59:43 +02002582/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002583static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002584smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002585 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002586{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002587 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002588 return 0;
2589
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002590 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002591 smp->flags = SMP_F_MAY_CHANGE;
2592 return 0;
2593 }
2594
2595 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002596 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002597 smp->flags = 0;
2598
2599 return 1;
2600}
2601
Emeric Brun2525b6b2012-10-18 15:59:43 +02002602/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002603static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002604smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002605 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002606{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002607 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002608 return 0;
2609
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002610 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002611 smp->flags = SMP_F_MAY_CHANGE;
2612 return 0;
2613 }
2614
2615 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002616 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002617 smp->flags = 0;
2618
2619 return 1;
2620}
2621
Emeric Brun2525b6b2012-10-18 15:59:43 +02002622/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002623static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002624smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002625 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002626{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002627 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002628 return 0;
2629
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002630 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002631 smp->flags = SMP_F_MAY_CHANGE;
2632 return 0;
2633 }
2634
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002635 if (!l4->si[0].conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002636 return 0;
2637
2638 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002639 smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002640 smp->flags = 0;
2641
2642 return 1;
2643}
2644
Emeric Brunfb510ea2012-10-05 12:00:26 +02002645/* parse the "ca-file" bind keyword */
2646static 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 +02002647{
2648 if (!*args[cur_arg + 1]) {
2649 if (err)
2650 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2651 return ERR_ALERT | ERR_FATAL;
2652 }
2653
Emeric Brunef42d922012-10-11 16:11:36 +02002654 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2655 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2656 else
2657 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002658
Emeric Brund94b3fe2012-09-20 18:23:56 +02002659 return 0;
2660}
2661
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002662/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002663static 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 +02002664{
2665 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002666 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002667 return ERR_ALERT | ERR_FATAL;
2668 }
2669
Emeric Brun76d88952012-10-05 15:47:31 +02002670 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002671 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002672 return 0;
2673}
2674
2675/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002676static 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 +02002677{
Willy Tarreau38011032013-08-13 16:59:39 +02002678 char path[MAXPATHLEN];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002679 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002680 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002681 return ERR_ALERT | ERR_FATAL;
2682 }
2683
Emeric Brunc8e8d122012-10-02 18:42:10 +02002684 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
Willy Tarreau38011032013-08-13 16:59:39 +02002685 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02002686 memprintf(err, "'%s' : path too long", args[cur_arg]);
2687 return ERR_ALERT | ERR_FATAL;
2688 }
2689 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2690 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2691 return ERR_ALERT | ERR_FATAL;
2692
2693 return 0;
2694 }
2695
Willy Tarreau4348fad2012-09-20 16:48:07 +02002696 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002697 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002698
2699 return 0;
2700}
2701
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002702/* parse the "crt-list" bind keyword */
2703static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2704{
2705 if (!*args[cur_arg + 1]) {
2706 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
2707 return ERR_ALERT | ERR_FATAL;
2708 }
2709
Willy Tarreauad1731d2013-04-02 17:35:58 +02002710 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
2711 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002712 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02002713 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002714
2715 return 0;
2716}
2717
Emeric Brunfb510ea2012-10-05 12:00:26 +02002718/* parse the "crl-file" bind keyword */
2719static 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 +02002720{
Emeric Brun051cdab2012-10-02 19:25:50 +02002721#ifndef X509_V_FLAG_CRL_CHECK
2722 if (err)
2723 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2724 return ERR_ALERT | ERR_FATAL;
2725#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002726 if (!*args[cur_arg + 1]) {
2727 if (err)
2728 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2729 return ERR_ALERT | ERR_FATAL;
2730 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002731
Emeric Brunef42d922012-10-11 16:11:36 +02002732 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2733 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2734 else
2735 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002736
Emeric Brun2b58d042012-09-20 17:10:03 +02002737 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002738#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002739}
2740
2741/* parse the "ecdhe" bind keyword keywords */
2742static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2743{
2744#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2745 if (err)
2746 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2747 return ERR_ALERT | ERR_FATAL;
2748#elif defined(OPENSSL_NO_ECDH)
2749 if (err)
2750 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2751 return ERR_ALERT | ERR_FATAL;
2752#else
2753 if (!*args[cur_arg + 1]) {
2754 if (err)
2755 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2756 return ERR_ALERT | ERR_FATAL;
2757 }
2758
2759 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002760
2761 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002762#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002763}
2764
Emeric Brun81c00f02012-09-21 14:31:21 +02002765/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2766static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2767{
2768 int code;
2769 char *p = args[cur_arg + 1];
2770 unsigned long long *ignerr = &conf->crt_ignerr;
2771
2772 if (!*p) {
2773 if (err)
2774 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2775 return ERR_ALERT | ERR_FATAL;
2776 }
2777
2778 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2779 ignerr = &conf->ca_ignerr;
2780
2781 if (strcmp(p, "all") == 0) {
2782 *ignerr = ~0ULL;
2783 return 0;
2784 }
2785
2786 while (p) {
2787 code = atoi(p);
2788 if ((code <= 0) || (code > 63)) {
2789 if (err)
2790 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2791 args[cur_arg], code, args[cur_arg + 1]);
2792 return ERR_ALERT | ERR_FATAL;
2793 }
2794 *ignerr |= 1ULL << code;
2795 p = strchr(p, ',');
2796 if (p)
2797 p++;
2798 }
2799
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002800 return 0;
2801}
2802
2803/* parse the "force-sslv3" bind keyword */
2804static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2805{
2806 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2807 return 0;
2808}
2809
2810/* parse the "force-tlsv10" bind keyword */
2811static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2812{
2813 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002814 return 0;
2815}
2816
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002817/* parse the "force-tlsv11" bind keyword */
2818static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2819{
2820#if SSL_OP_NO_TLSv1_1
2821 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
2822 return 0;
2823#else
2824 if (err)
2825 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
2826 return ERR_ALERT | ERR_FATAL;
2827#endif
2828}
2829
2830/* parse the "force-tlsv12" bind keyword */
2831static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2832{
2833#if SSL_OP_NO_TLSv1_2
2834 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
2835 return 0;
2836#else
2837 if (err)
2838 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
2839 return ERR_ALERT | ERR_FATAL;
2840#endif
2841}
2842
2843
Emeric Brun2d0c4822012-10-02 13:45:20 +02002844/* parse the "no-tls-tickets" bind keyword */
2845static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2846{
Emeric Brun89675492012-10-05 13:48:26 +02002847 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02002848 return 0;
2849}
2850
Emeric Brun2d0c4822012-10-02 13:45:20 +02002851
Emeric Brun9b3009b2012-10-05 11:55:06 +02002852/* parse the "no-sslv3" bind keyword */
2853static 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 +02002854{
Emeric Brun89675492012-10-05 13:48:26 +02002855 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002856 return 0;
2857}
2858
Emeric Brun9b3009b2012-10-05 11:55:06 +02002859/* parse the "no-tlsv10" bind keyword */
2860static 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 +02002861{
Emeric Brun89675492012-10-05 13:48:26 +02002862 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002863 return 0;
2864}
2865
Emeric Brun9b3009b2012-10-05 11:55:06 +02002866/* parse the "no-tlsv11" bind keyword */
2867static 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 +02002868{
Emeric Brun89675492012-10-05 13:48:26 +02002869 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002870 return 0;
2871}
2872
Emeric Brun9b3009b2012-10-05 11:55:06 +02002873/* parse the "no-tlsv12" bind keyword */
2874static 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 +02002875{
Emeric Brun89675492012-10-05 13:48:26 +02002876 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002877 return 0;
2878}
2879
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002880/* parse the "npn" bind keyword */
2881static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2882{
2883#ifdef OPENSSL_NPN_NEGOTIATED
2884 char *p1, *p2;
2885
2886 if (!*args[cur_arg + 1]) {
2887 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
2888 return ERR_ALERT | ERR_FATAL;
2889 }
2890
2891 free(conf->npn_str);
2892
2893 /* the NPN string is built as a suite of (<len> <name>)* */
2894 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
2895 conf->npn_str = calloc(1, conf->npn_len);
2896 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
2897
2898 /* replace commas with the name length */
2899 p1 = conf->npn_str;
2900 p2 = p1 + 1;
2901 while (1) {
2902 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
2903 if (!p2)
2904 p2 = p1 + 1 + strlen(p1 + 1);
2905
2906 if (p2 - (p1 + 1) > 255) {
2907 *p2 = '\0';
2908 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2909 return ERR_ALERT | ERR_FATAL;
2910 }
2911
2912 *p1 = p2 - (p1 + 1);
2913 p1 = p2;
2914
2915 if (!*p2)
2916 break;
2917
2918 *(p2++) = '\0';
2919 }
2920 return 0;
2921#else
2922 if (err)
2923 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
2924 return ERR_ALERT | ERR_FATAL;
2925#endif
2926}
2927
Willy Tarreauab861d32013-04-02 02:30:41 +02002928/* parse the "alpn" bind keyword */
2929static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2930{
2931#ifdef OPENSSL_ALPN_NEGOTIATED
2932 char *p1, *p2;
2933
2934 if (!*args[cur_arg + 1]) {
2935 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
2936 return ERR_ALERT | ERR_FATAL;
2937 }
2938
2939 free(conf->alpn_str);
2940
2941 /* the ALPN string is built as a suite of (<len> <name>)* */
2942 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
2943 conf->alpn_str = calloc(1, conf->alpn_len);
2944 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
2945
2946 /* replace commas with the name length */
2947 p1 = conf->alpn_str;
2948 p2 = p1 + 1;
2949 while (1) {
2950 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
2951 if (!p2)
2952 p2 = p1 + 1 + strlen(p1 + 1);
2953
2954 if (p2 - (p1 + 1) > 255) {
2955 *p2 = '\0';
2956 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2957 return ERR_ALERT | ERR_FATAL;
2958 }
2959
2960 *p1 = p2 - (p1 + 1);
2961 p1 = p2;
2962
2963 if (!*p2)
2964 break;
2965
2966 *(p2++) = '\0';
2967 }
2968 return 0;
2969#else
2970 if (err)
2971 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
2972 return ERR_ALERT | ERR_FATAL;
2973#endif
2974}
2975
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002976/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002977static 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 +02002978{
Willy Tarreau81796be2012-09-22 19:11:47 +02002979 struct listener *l;
2980
Willy Tarreau4348fad2012-09-20 16:48:07 +02002981 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02002982
2983 if (global.listen_default_ciphers && !conf->ciphers)
2984 conf->ciphers = strdup(global.listen_default_ciphers);
2985
Willy Tarreau81796be2012-09-22 19:11:47 +02002986 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002987 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02002988
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002989 return 0;
2990}
2991
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002992/* parse the "strict-sni" bind keyword */
2993static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2994{
2995 conf->strict_sni = 1;
2996 return 0;
2997}
2998
Emeric Brund94b3fe2012-09-20 18:23:56 +02002999/* parse the "verify" bind keyword */
3000static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3001{
3002 if (!*args[cur_arg + 1]) {
3003 if (err)
3004 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
3005 return ERR_ALERT | ERR_FATAL;
3006 }
3007
3008 if (strcmp(args[cur_arg + 1], "none") == 0)
3009 conf->verify = SSL_VERIFY_NONE;
3010 else if (strcmp(args[cur_arg + 1], "optional") == 0)
3011 conf->verify = SSL_VERIFY_PEER;
3012 else if (strcmp(args[cur_arg + 1], "required") == 0)
3013 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
3014 else {
3015 if (err)
3016 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
3017 args[cur_arg], args[cur_arg + 1]);
3018 return ERR_ALERT | ERR_FATAL;
3019 }
3020
3021 return 0;
3022}
3023
Willy Tarreau92faadf2012-10-10 23:04:25 +02003024/************** "server" keywords ****************/
3025
Emeric Brunef42d922012-10-11 16:11:36 +02003026/* parse the "ca-file" server keyword */
3027static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3028{
3029 if (!*args[*cur_arg + 1]) {
3030 if (err)
3031 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
3032 return ERR_ALERT | ERR_FATAL;
3033 }
3034
3035 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3036 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3037 else
3038 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
3039
3040 return 0;
3041}
3042
Willy Tarreau92faadf2012-10-10 23:04:25 +02003043/* parse the "check-ssl" server keyword */
3044static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3045{
3046 newsrv->check.use_ssl = 1;
3047 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3048 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3049 return 0;
3050}
3051
3052/* parse the "ciphers" server keyword */
3053static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3054{
3055 if (!*args[*cur_arg + 1]) {
3056 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
3057 return ERR_ALERT | ERR_FATAL;
3058 }
3059
3060 free(newsrv->ssl_ctx.ciphers);
3061 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
3062 return 0;
3063}
3064
Emeric Brunef42d922012-10-11 16:11:36 +02003065/* parse the "crl-file" server keyword */
3066static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3067{
3068#ifndef X509_V_FLAG_CRL_CHECK
3069 if (err)
3070 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
3071 return ERR_ALERT | ERR_FATAL;
3072#else
3073 if (!*args[*cur_arg + 1]) {
3074 if (err)
3075 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
3076 return ERR_ALERT | ERR_FATAL;
3077 }
3078
3079 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3080 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3081 else
3082 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
3083
3084 return 0;
3085#endif
3086}
3087
Emeric Bruna7aa3092012-10-26 12:58:00 +02003088/* parse the "crt" server keyword */
3089static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3090{
3091 if (!*args[*cur_arg + 1]) {
3092 if (err)
3093 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
3094 return ERR_ALERT | ERR_FATAL;
3095 }
3096
3097 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
3098 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3099 else
3100 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
3101
3102 return 0;
3103}
Emeric Brunef42d922012-10-11 16:11:36 +02003104
Willy Tarreau92faadf2012-10-10 23:04:25 +02003105/* parse the "force-sslv3" server keyword */
3106static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3107{
3108 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
3109 return 0;
3110}
3111
3112/* parse the "force-tlsv10" server keyword */
3113static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3114{
3115 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
3116 return 0;
3117}
3118
3119/* parse the "force-tlsv11" server keyword */
3120static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3121{
3122#if SSL_OP_NO_TLSv1_1
3123 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
3124 return 0;
3125#else
3126 if (err)
3127 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
3128 return ERR_ALERT | ERR_FATAL;
3129#endif
3130}
3131
3132/* parse the "force-tlsv12" server keyword */
3133static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3134{
3135#if SSL_OP_NO_TLSv1_2
3136 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
3137 return 0;
3138#else
3139 if (err)
3140 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
3141 return ERR_ALERT | ERR_FATAL;
3142#endif
3143}
3144
3145/* parse the "no-sslv3" server keyword */
3146static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3147{
3148 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
3149 return 0;
3150}
3151
3152/* parse the "no-tlsv10" server keyword */
3153static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3154{
3155 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
3156 return 0;
3157}
3158
3159/* parse the "no-tlsv11" server keyword */
3160static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3161{
3162 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
3163 return 0;
3164}
3165
3166/* parse the "no-tlsv12" server keyword */
3167static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3168{
3169 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
3170 return 0;
3171}
3172
Emeric Brunf9c5c472012-10-11 15:28:34 +02003173/* parse the "no-tls-tickets" server keyword */
3174static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3175{
3176 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
3177 return 0;
3178}
3179
Willy Tarreau92faadf2012-10-10 23:04:25 +02003180/* parse the "ssl" server keyword */
3181static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3182{
3183 newsrv->use_ssl = 1;
3184 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3185 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3186 return 0;
3187}
3188
Emeric Brunef42d922012-10-11 16:11:36 +02003189/* parse the "verify" server keyword */
3190static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3191{
3192 if (!*args[*cur_arg + 1]) {
3193 if (err)
3194 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
3195 return ERR_ALERT | ERR_FATAL;
3196 }
3197
3198 if (strcmp(args[*cur_arg + 1], "none") == 0)
3199 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
3200 else if (strcmp(args[*cur_arg + 1], "required") == 0)
3201 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
3202 else {
3203 if (err)
3204 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
3205 args[*cur_arg], args[*cur_arg + 1]);
3206 return ERR_ALERT | ERR_FATAL;
3207 }
3208
Evan Broderbe554312013-06-27 00:05:25 -07003209 return 0;
3210}
3211
3212/* parse the "verifyhost" server keyword */
3213static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3214{
3215 if (!*args[*cur_arg + 1]) {
3216 if (err)
3217 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
3218 return ERR_ALERT | ERR_FATAL;
3219 }
3220
3221 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
3222
Emeric Brunef42d922012-10-11 16:11:36 +02003223 return 0;
3224}
3225
Willy Tarreau7875d092012-09-10 08:20:03 +02003226/* Note: must not be declared <const> as its list will be overwritten.
3227 * Please take care of keeping this list alphabetically sorted.
3228 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003229static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Willy Tarreau80aca902013-01-07 15:42:20 +01003230 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3231 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3232 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3233 { "ssl_c_i_dn", smp_fetch_ssl_c_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3234 { "ssl_c_key_alg", smp_fetch_ssl_c_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3235 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3236 { "ssl_c_notbefore", smp_fetch_ssl_c_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3237 { "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3238 { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3239 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
James Votha051b4a2013-05-14 20:37:59 +02003240 { "ssl_c_sha1", smp_fetch_ssl_c_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01003241 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3242 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3243 { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3244 { "ssl_f_i_dn", smp_fetch_ssl_f_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3245 { "ssl_f_key_alg", smp_fetch_ssl_f_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3246 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3247 { "ssl_f_notbefore", smp_fetch_ssl_f_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3248 { "ssl_f_sig_alg", smp_fetch_ssl_f_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3249 { "ssl_f_s_dn", smp_fetch_ssl_f_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3250 { "ssl_f_serial", smp_fetch_ssl_f_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3251 { "ssl_f_version", smp_fetch_ssl_f_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3252 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3253 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3254 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3255 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3256 { "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 +02003257#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau80aca902013-01-07 15:42:20 +01003258 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003259#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003260#ifdef OPENSSL_ALPN_NEGOTIATED
3261 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3262#endif
Willy Tarreau80aca902013-01-07 15:42:20 +01003263 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3264 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3265 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_CBIN, SMP_USE_L5CLI },
3266 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreau7875d092012-09-10 08:20:03 +02003267 { NULL, NULL, 0, 0, 0 },
3268}};
3269
3270/* Note: must not be declared <const> as its list will be overwritten.
3271 * Please take care of keeping this list alphabetically sorted.
3272 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003273static struct acl_kw_list acl_kws = {ILH, {
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003274 { "ssl_c_i_dn", NULL, acl_parse_str, acl_match_str },
3275 { "ssl_c_key_alg", NULL, acl_parse_str, acl_match_str },
3276 { "ssl_c_notafter", NULL, acl_parse_str, acl_match_str },
3277 { "ssl_c_notbefore", NULL, acl_parse_str, acl_match_str },
3278 { "ssl_c_sig_alg", NULL, acl_parse_str, acl_match_str },
3279 { "ssl_c_s_dn", NULL, acl_parse_str, acl_match_str },
3280 { "ssl_c_serial", NULL, acl_parse_bin, acl_match_bin },
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003281 { "ssl_f_i_dn", NULL, acl_parse_str, acl_match_str },
3282 { "ssl_f_key_alg", NULL, acl_parse_str, acl_match_str },
3283 { "ssl_f_notafter", NULL, acl_parse_str, acl_match_str },
3284 { "ssl_f_notbefore", NULL, acl_parse_str, acl_match_str },
3285 { "ssl_f_sig_alg", NULL, acl_parse_str, acl_match_str },
3286 { "ssl_f_s_dn", NULL, acl_parse_str, acl_match_str },
3287 { "ssl_f_serial", NULL, acl_parse_bin, acl_match_bin },
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003288 { "ssl_fc_cipher", NULL, acl_parse_str, acl_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003289#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003290 { "ssl_fc_npn", NULL, acl_parse_str, acl_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003291#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003292#ifdef OPENSSL_ALPN_NEGOTIATED
3293 { "ssl_fc_alpn", NULL, acl_parse_str, acl_match_str },
3294#endif
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003295 { "ssl_fc_protocol", NULL, acl_parse_str, acl_match_str },
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003296 { "ssl_fc_sni", "ssl_fc_sni", acl_parse_str, acl_match_str },
3297 { "ssl_fc_sni_end", "ssl_fc_sni", acl_parse_str, acl_match_end },
3298 { "ssl_fc_sni_reg", "ssl_fc_sni", acl_parse_reg, acl_match_reg },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01003299 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02003300}};
3301
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003302/* Note: must not be declared <const> as its list will be overwritten.
3303 * Please take care of keeping this list alphabetically sorted, doing so helps
3304 * all code contributors.
3305 * Optional keywords are also declared with a NULL ->parse() function so that
3306 * the config parser can report an appropriate error when a known keyword was
3307 * not enabled.
3308 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02003309static struct bind_kw_list bind_kws = { "SSL", { }, {
Willy Tarreauab861d32013-04-02 02:30:41 +02003310 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003311 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003312 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
3313 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003314 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003315 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
3316 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003317 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003318 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003319 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
3320 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
3321 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
3322 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02003323 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
3324 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
3325 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
3326 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003327 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003328 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003329 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003330 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003331 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003332 { NULL, NULL, 0 },
3333}};
Emeric Brun46591952012-05-18 15:47:34 +02003334
Willy Tarreau92faadf2012-10-10 23:04:25 +02003335/* Note: must not be declared <const> as its list will be overwritten.
3336 * Please take care of keeping this list alphabetically sorted, doing so helps
3337 * all code contributors.
3338 * Optional keywords are also declared with a NULL ->parse() function so that
3339 * the config parser can report an appropriate error when a known keyword was
3340 * not enabled.
3341 */
3342static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02003343 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003344 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
3345 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02003346 { "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 +02003347 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003348 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
3349 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
3350 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
3351 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
3352 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
3353 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
3354 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
3355 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02003356 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003357 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02003358 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Evan Broderbe554312013-06-27 00:05:25 -07003359 { "verifyhost", srv_parse_verifyhost, 1, 0 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02003360 { NULL, NULL, 0, 0 },
3361}};
3362
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003363/* transport-layer operations for SSL sockets */
3364struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02003365 .snd_buf = ssl_sock_from_buf,
3366 .rcv_buf = ssl_sock_to_buf,
3367 .rcv_pipe = NULL,
3368 .snd_pipe = NULL,
3369 .shutr = NULL,
3370 .shutw = ssl_sock_shutw,
3371 .close = ssl_sock_close,
3372 .init = ssl_sock_init,
3373};
3374
3375__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02003376static void __ssl_sock_init(void)
3377{
Emeric Brun46591952012-05-18 15:47:34 +02003378 STACK_OF(SSL_COMP)* cm;
3379
3380 SSL_library_init();
3381 cm = SSL_COMP_get_compression_methods();
3382 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02003383 sample_register_fetches(&sample_fetch_keywords);
3384 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003385 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02003386 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02003387}
3388
3389/*
3390 * Local variables:
3391 * c-indent-level: 8
3392 * c-basic-offset: 8
3393 * End:
3394 */