blob: 105aa1d3bb80bb84508eef706f57b8a6d5dbda59 [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
781 /* If it's not trivial and there are no wildcards, it can't
782 * match */
783 if (!(pattern_wildcard = strchr(pattern, '*')))
784 return 0;
785
786 /* The rest of this logic is based on RFC 6125, section 6.4.3
787 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
788
789 /* Make sure the wildcard occurs in the leftmost label */
790 pattern_left_label_end = strchr(pattern, '.');
791 if (!pattern_left_label_end
792 || pattern_left_label_end < pattern_wildcard)
793 return 0;
794
795 /* Make sure all labels match except the leftmost */
796 hostname_left_label_end = strchr(hostname, '.');
797 if (!hostname_left_label_end
798 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
799 return 0;
800
801 /* Make sure the leftmost label of the hostname is long enough
802 * that the wildcard can match */
803 if (hostname_left_label_end - hostname < pattern_left_label_end - pattern)
804 return 0;
805
806 /* Finally compare the string on either side of the
807 * wildcard */
808 prefixlen = pattern_wildcard - pattern;
809 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
810 if (strncmp(pattern, hostname, prefixlen) != 0
811 || strncmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)
812 return 0;
813
814 return 1;
815}
816
817static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
818{
819 SSL *ssl;
820 struct connection *conn;
821 char *servername;
822
823 int depth;
824 X509 *cert;
825 STACK_OF(GENERAL_NAME) *alt_names;
826 int i;
827 X509_NAME *cert_subject;
828 char *str;
829
830 if (ok == 0)
831 return ok;
832
833 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
834 conn = (struct connection *)SSL_get_app_data(ssl);
835
836 servername = objt_server(conn->target)->ssl_ctx.verify_host;
837
838 /* We only need to verify the CN on the actual server cert,
839 * not the indirect CAs */
840 depth = X509_STORE_CTX_get_error_depth(ctx);
841 if (depth != 0)
842 return ok;
843
844 /* At this point, the cert is *not* OK unless we can find a
845 * hostname match */
846 ok = 0;
847
848 cert = X509_STORE_CTX_get_current_cert(ctx);
849 /* It seems like this might happen if verify peer isn't set */
850 if (!cert)
851 return ok;
852
853 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
854 if (alt_names) {
855 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
856 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
857 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +0200858#if OPENSSL_VERSION_NUMBER < 0x00907000L
859 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
860#else
Evan Broderbe554312013-06-27 00:05:25 -0700861 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +0200862#endif
Evan Broderbe554312013-06-27 00:05:25 -0700863 ok = ssl_sock_srv_hostcheck(str, servername);
864 OPENSSL_free(str);
865 }
866 }
867 }
Emeric Brun4ad50a42013-09-17 15:19:54 +0200868 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -0700869 }
870
871 cert_subject = X509_get_subject_name(cert);
872 i = -1;
873 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
874 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
875 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
876 ok = ssl_sock_srv_hostcheck(str, servername);
877 OPENSSL_free(str);
878 }
879 }
880
881 return ok;
882}
883
Emeric Brun94324a42012-10-11 14:00:19 +0200884/* prepare ssl context from servers options. Returns an error count */
885int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
886{
887 int cfgerr = 0;
888 int options =
889 SSL_OP_ALL | /* all known workarounds for bugs */
890 SSL_OP_NO_SSLv2 |
891 SSL_OP_NO_COMPRESSION;
892 int mode =
893 SSL_MODE_ENABLE_PARTIAL_WRITE |
894 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
895 SSL_MODE_RELEASE_BUFFERS;
896
Thierry Fournier383085f2013-01-24 14:15:43 +0100897 /* Make sure openssl opens /dev/urandom before the chroot */
898 if (!ssl_initialize_random()) {
899 Alert("OpenSSL random data generator initialization failed.\n");
900 cfgerr++;
901 }
902
Emeric Brun94324a42012-10-11 14:00:19 +0200903 /* Initiate SSL context for current server */
904 srv->ssl_ctx.reused_sess = NULL;
905 if (srv->use_ssl)
906 srv->xprt = &ssl_sock;
907 if (srv->check.use_ssl)
908 srv->check.xprt = &ssl_sock;
909
910 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
911 if (!srv->ssl_ctx.ctx) {
912 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
913 proxy_type_str(curproxy), curproxy->id,
914 srv->id);
915 cfgerr++;
916 return cfgerr;
917 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200918 if (srv->ssl_ctx.client_crt) {
919 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
920 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
921 proxy_type_str(curproxy), curproxy->id,
922 srv->id, srv->ssl_ctx.client_crt);
923 cfgerr++;
924 }
925 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
926 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
927 proxy_type_str(curproxy), curproxy->id,
928 srv->id, srv->ssl_ctx.client_crt);
929 cfgerr++;
930 }
931 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
932 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
933 proxy_type_str(curproxy), curproxy->id,
934 srv->id, srv->ssl_ctx.client_crt);
935 cfgerr++;
936 }
937 }
Emeric Brun94324a42012-10-11 14:00:19 +0200938
939 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
940 options |= SSL_OP_NO_SSLv3;
941 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
942 options |= SSL_OP_NO_TLSv1;
943 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
944 options |= SSL_OP_NO_TLSv1_1;
945 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
946 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200947 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
948 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200949 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
950 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
951 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
952 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
953#if SSL_OP_NO_TLSv1_1
954 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
955 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
956#endif
957#if SSL_OP_NO_TLSv1_2
958 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
959 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
960#endif
961
962 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
963 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Evan Broderbe554312013-06-27 00:05:25 -0700964 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
965 srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE,
966 srv->ssl_ctx.verify_host ? ssl_sock_srv_verifycbk : NULL);
Emeric Brunef42d922012-10-11 16:11:36 +0200967 if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
968 if (srv->ssl_ctx.ca_file) {
969 /* load CAfile to verify */
970 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
971 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
972 curproxy->id, srv->id,
973 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
974 cfgerr++;
975 }
976 }
977#ifdef X509_V_FLAG_CRL_CHECK
978 if (srv->ssl_ctx.crl_file) {
979 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
980
981 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
982 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
983 curproxy->id, srv->id,
984 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
985 cfgerr++;
986 }
987 else {
988 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
989 }
990 }
991#endif
992 }
993
Emeric Brun4f65bff2012-11-16 15:11:00 +0100994 if (global.tune.ssllifetime)
995 SSL_CTX_set_timeout(srv->ssl_ctx.ctx, global.tune.ssllifetime);
996
Emeric Brun94324a42012-10-11 14:00:19 +0200997 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
998 if (srv->ssl_ctx.ciphers &&
999 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
1000 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
1001 curproxy->id, srv->id,
1002 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
1003 cfgerr++;
1004 }
1005
1006 return cfgerr;
1007}
1008
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001009/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02001010 * be NULL, in which case nothing is done. Returns the number of errors
1011 * encountered.
1012 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001013int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001014{
1015 struct ebmb_node *node;
1016 struct sni_ctx *sni;
1017 int err = 0;
1018
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001019 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001020 return 0;
1021
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001022 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001023 while (node) {
1024 sni = ebmb_entry(node, struct sni_ctx, name);
1025 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001026 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001027 node = ebmb_next(node);
1028 }
1029
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001030 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001031 while (node) {
1032 sni = ebmb_entry(node, struct sni_ctx, name);
1033 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001034 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001035 node = ebmb_next(node);
1036 }
1037 return err;
1038}
1039
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001040/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02001041 * be NULL, in which case nothing is done. The default_ctx is nullified too.
1042 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001043void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001044{
1045 struct ebmb_node *node, *back;
1046 struct sni_ctx *sni;
1047
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001048 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001049 return;
1050
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001051 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001052 while (node) {
1053 sni = ebmb_entry(node, struct sni_ctx, name);
1054 back = ebmb_next(node);
1055 ebmb_delete(node);
1056 if (!sni->order) /* only free the CTX on its first occurrence */
1057 SSL_CTX_free(sni->ctx);
1058 free(sni);
1059 node = back;
1060 }
1061
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001062 node = ebmb_first(&bind_conf->sni_w_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 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02001074}
1075
Emeric Brun46591952012-05-18 15:47:34 +02001076/*
1077 * This function is called if SSL * context is not yet allocated. The function
1078 * is designed to be called before any other data-layer operation and sets the
1079 * handshake flag on the connection. It is safe to call it multiple times.
1080 * It returns 0 on success and -1 in error case.
1081 */
1082static int ssl_sock_init(struct connection *conn)
1083{
1084 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001085 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001086 return 0;
1087
Willy Tarreau20879a02012-12-03 16:32:10 +01001088 if (global.maxsslconn && sslconns >= global.maxsslconn) {
1089 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02001090 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001091 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001092
Emeric Brun46591952012-05-18 15:47:34 +02001093 /* If it is in client mode initiate SSL session
1094 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001095 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001096 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001097 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001098 if (!conn->xprt_ctx) {
1099 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001100 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001101 }
Emeric Brun46591952012-05-18 15:47:34 +02001102
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001103 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001104 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1105 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001106
1107 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001108 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001109
Evan Broderbe554312013-06-27 00:05:25 -07001110 /* set connection pointer */
1111 SSL_set_app_data(conn->xprt_ctx, conn);
1112
Emeric Brun46591952012-05-18 15:47:34 +02001113 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001114 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001115
1116 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001117 return 0;
1118 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001119 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001120 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001121 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001122 if (!conn->xprt_ctx) {
1123 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001124 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001125 }
Emeric Brun46591952012-05-18 15:47:34 +02001126
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001127 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001128
1129 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001130 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001131
Emeric Brune1f38db2012-09-03 20:36:47 +02001132 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001133 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +02001134
Emeric Brun46591952012-05-18 15:47:34 +02001135 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001136 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001137
1138 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001139 return 0;
1140 }
1141 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01001142 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02001143 return -1;
1144}
1145
1146
1147/* This is the callback which is used when an SSL handshake is pending. It
1148 * updates the FD status if it wants some polling before being called again.
1149 * It returns 0 if it fails in a fatal way or needs to poll to go further,
1150 * otherwise it returns non-zero and removes itself from the connection's
1151 * flags (the bit is provided in <flag> by the caller).
1152 */
1153int ssl_sock_handshake(struct connection *conn, unsigned int flag)
1154{
1155 int ret;
1156
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001157 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001158 goto out_error;
1159
Emeric Brun674b7432012-11-08 19:21:55 +01001160 /* If we use SSL_do_handshake to process a reneg initiated by
1161 * the remote peer, it sometimes returns SSL_ERROR_SSL.
1162 * Usually SSL_write and SSL_read are used and process implicitly
1163 * the reneg handshake.
1164 * Here we use SSL_peek as a workaround for reneg.
1165 */
1166 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
1167 char c;
1168
1169 ret = SSL_peek(conn->xprt_ctx, &c, 1);
1170 if (ret <= 0) {
1171 /* handshake may have not been completed, let's find why */
1172 ret = SSL_get_error(conn->xprt_ctx, ret);
1173 if (ret == SSL_ERROR_WANT_WRITE) {
1174 /* SSL handshake needs to write, L4 connection may not be ready */
1175 __conn_sock_stop_recv(conn);
1176 __conn_sock_poll_send(conn);
1177 return 0;
1178 }
1179 else if (ret == SSL_ERROR_WANT_READ) {
1180 /* handshake may have been completed but we have
1181 * no more data to read.
1182 */
1183 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
1184 ret = 1;
1185 goto reneg_ok;
1186 }
1187 /* SSL handshake needs to read, L4 connection is ready */
1188 if (conn->flags & CO_FL_WAIT_L4_CONN)
1189 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1190 __conn_sock_stop_send(conn);
1191 __conn_sock_poll_recv(conn);
1192 return 0;
1193 }
1194 else if (ret == SSL_ERROR_SYSCALL) {
1195 /* if errno is null, then connection was successfully established */
1196 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1197 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001198 if (!conn->err_code) {
1199 if (!((SSL *)conn->xprt_ctx)->packet_length)
1200 if (!errno)
1201 conn->err_code = CO_ER_SSL_EMPTY;
1202 else
1203 conn->err_code = CO_ER_SSL_ABORT;
1204 else
1205 conn->err_code = CO_ER_SSL_HANDSHAKE;
1206 }
Emeric Brun674b7432012-11-08 19:21:55 +01001207 goto out_error;
1208 }
1209 else {
1210 /* Fail on all other handshake errors */
1211 /* Note: OpenSSL may leave unread bytes in the socket's
1212 * buffer, causing an RST to be emitted upon close() on
1213 * TCP sockets. We first try to drain possibly pending
1214 * data to avoid this as much as possible.
1215 */
Willy Tarreau2b57cb82013-06-10 19:56:38 +02001216 if (conn->ctrl && conn->ctrl->drain)
1217 conn->ctrl->drain(conn->t.sock.fd);
Willy Tarreau20879a02012-12-03 16:32:10 +01001218 if (!conn->err_code)
1219 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01001220 goto out_error;
1221 }
1222 }
1223 /* read some data: consider handshake completed */
1224 goto reneg_ok;
1225 }
1226
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001227 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001228 if (ret != 1) {
1229 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001230 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001231
1232 if (ret == SSL_ERROR_WANT_WRITE) {
1233 /* SSL handshake needs to write, L4 connection may not be ready */
1234 __conn_sock_stop_recv(conn);
1235 __conn_sock_poll_send(conn);
1236 return 0;
1237 }
1238 else if (ret == SSL_ERROR_WANT_READ) {
1239 /* SSL handshake needs to read, L4 connection is ready */
1240 if (conn->flags & CO_FL_WAIT_L4_CONN)
1241 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1242 __conn_sock_stop_send(conn);
1243 __conn_sock_poll_recv(conn);
1244 return 0;
1245 }
Willy Tarreau89230192012-09-28 20:22:13 +02001246 else if (ret == SSL_ERROR_SYSCALL) {
1247 /* if errno is null, then connection was successfully established */
1248 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1249 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001250
1251 if (!((SSL *)conn->xprt_ctx)->packet_length)
1252 if (!errno)
1253 conn->err_code = CO_ER_SSL_EMPTY;
1254 else
1255 conn->err_code = CO_ER_SSL_ABORT;
1256 else
1257 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +02001258 goto out_error;
1259 }
Emeric Brun46591952012-05-18 15:47:34 +02001260 else {
1261 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02001262 /* Note: OpenSSL may leave unread bytes in the socket's
1263 * buffer, causing an RST to be emitted upon close() on
1264 * TCP sockets. We first try to drain possibly pending
1265 * data to avoid this as much as possible.
1266 */
Willy Tarreau2b57cb82013-06-10 19:56:38 +02001267 if (conn->ctrl && conn->ctrl->drain)
1268 conn->ctrl->drain(conn->t.sock.fd);
Willy Tarreau20879a02012-12-03 16:32:10 +01001269 if (!conn->err_code)
1270 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001271 goto out_error;
1272 }
1273 }
1274
Emeric Brun674b7432012-11-08 19:21:55 +01001275reneg_ok:
1276
Emeric Brun46591952012-05-18 15:47:34 +02001277 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001278 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001279 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +02001280 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001281 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1282 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001283
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001284 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001285 }
1286 }
1287
1288 /* The connection is now established at both layers, it's time to leave */
1289 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1290 return 1;
1291
1292 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001293 /* Clear openssl global errors stack */
1294 ERR_clear_error();
1295
Emeric Brun9fa89732012-10-04 17:09:56 +02001296 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001297 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1298 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1299 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001300 }
1301
Emeric Brun46591952012-05-18 15:47:34 +02001302 /* Fail on all other handshake errors */
1303 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001304 if (!conn->err_code)
1305 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001306 return 0;
1307}
1308
1309/* Receive up to <count> bytes from connection <conn>'s socket and store them
1310 * into buffer <buf>. The caller must ensure that <count> is always smaller
1311 * than the buffer's size. Only one call to recv() is performed, unless the
1312 * buffer wraps, in which case a second call may be performed. The connection's
1313 * flags are updated with whatever special event is detected (error, read0,
1314 * empty). The caller is responsible for taking care of those events and
1315 * avoiding the call if inappropriate. The function does not call the
1316 * connection's polling update function, so the caller is responsible for this.
1317 */
1318static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1319{
1320 int ret, done = 0;
1321 int try = count;
1322
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001323 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001324 goto out_error;
1325
1326 if (conn->flags & CO_FL_HANDSHAKE)
1327 /* a handshake was requested */
1328 return 0;
1329
1330 /* compute the maximum block size we can read at once. */
1331 if (buffer_empty(buf)) {
1332 /* let's realign the buffer to optimize I/O */
1333 buf->p = buf->data;
1334 }
1335 else if (buf->data + buf->o < buf->p &&
1336 buf->p + buf->i < buf->data + buf->size) {
1337 /* remaining space wraps at the end, with a moving limit */
1338 if (try > buf->data + buf->size - (buf->p + buf->i))
1339 try = buf->data + buf->size - (buf->p + buf->i);
1340 }
1341
1342 /* read the largest possible block. For this, we perform only one call
1343 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1344 * in which case we accept to do it once again. A new attempt is made on
1345 * EINTR too.
1346 */
1347 while (try) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001348 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001349 if (conn->flags & CO_FL_ERROR) {
1350 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001351 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001352 }
Emeric Brun46591952012-05-18 15:47:34 +02001353 if (ret > 0) {
1354 buf->i += ret;
1355 done += ret;
1356 if (ret < try)
1357 break;
1358 count -= ret;
1359 try = count;
1360 }
1361 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001362 ret = SSL_get_error(conn->xprt_ctx, ret);
1363 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001364 /* error on protocol or underlying transport */
1365 if ((ret != SSL_ERROR_SYSCALL)
1366 || (errno && (errno != EAGAIN)))
1367 conn->flags |= CO_FL_ERROR;
1368
Emeric Brun644cde02012-12-14 11:21:13 +01001369 /* Clear openssl global errors stack */
1370 ERR_clear_error();
1371 }
Emeric Brun46591952012-05-18 15:47:34 +02001372 goto read0;
1373 }
1374 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001375 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001376 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001377 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001378 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001379 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001380 break;
1381 }
1382 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001383 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1384 /* handshake is running, and it may need to re-enable read */
1385 conn->flags |= CO_FL_SSL_WAIT_HS;
1386 __conn_sock_want_recv(conn);
1387 break;
1388 }
Emeric Brun46591952012-05-18 15:47:34 +02001389 /* we need to poll for retry a read later */
1390 __conn_data_poll_recv(conn);
1391 break;
1392 }
1393 /* otherwise it's a real error */
1394 goto out_error;
1395 }
1396 }
1397 return done;
1398
1399 read0:
1400 conn_sock_read0(conn);
1401 return done;
1402 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001403 /* Clear openssl global errors stack */
1404 ERR_clear_error();
1405
Emeric Brun46591952012-05-18 15:47:34 +02001406 conn->flags |= CO_FL_ERROR;
1407 return done;
1408}
1409
1410
1411/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1412 * <flags> may contain MSG_MORE to make the system hold on without sending
1413 * data too fast, but this flag is ignored at the moment.
1414 * Only one call to send() is performed, unless the buffer wraps, in which case
1415 * a second call may be performed. The connection's flags are updated with
1416 * whatever special event is detected (error, empty). The caller is responsible
1417 * for taking care of those events and avoiding the call if inappropriate. The
1418 * function does not call the connection's polling update function, so the caller
1419 * is responsible for this.
1420 */
1421static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1422{
1423 int ret, try, done;
1424
1425 done = 0;
1426
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001427 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001428 goto out_error;
1429
1430 if (conn->flags & CO_FL_HANDSHAKE)
1431 /* a handshake was requested */
1432 return 0;
1433
1434 /* send the largest possible block. For this we perform only one call
1435 * to send() unless the buffer wraps and we exactly fill the first hunk,
1436 * in which case we accept to do it once again.
1437 */
1438 while (buf->o) {
Kevin Hestercad82342013-05-30 15:12:41 -07001439 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01001440
1441 if (global.tune.ssl_max_record && try > global.tune.ssl_max_record)
1442 try = global.tune.ssl_max_record;
1443
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001444 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001445 if (conn->flags & CO_FL_ERROR) {
1446 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001447 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001448 }
Emeric Brun46591952012-05-18 15:47:34 +02001449 if (ret > 0) {
1450 buf->o -= ret;
1451 done += ret;
1452
Willy Tarreau5fb38032012-12-16 19:39:09 +01001453 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001454 /* optimize data alignment in the buffer */
1455 buf->p = buf->data;
1456
1457 /* if the system buffer is full, don't insist */
1458 if (ret < try)
1459 break;
1460 }
1461 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001462 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001463 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001464 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1465 /* handshake is running, and it may need to re-enable write */
1466 conn->flags |= CO_FL_SSL_WAIT_HS;
1467 __conn_sock_want_send(conn);
1468 break;
1469 }
Emeric Brun46591952012-05-18 15:47:34 +02001470 /* we need to poll to retry a write later */
1471 __conn_data_poll_send(conn);
1472 break;
1473 }
1474 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001475 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001476 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001477 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001478 break;
1479 }
1480 goto out_error;
1481 }
1482 }
1483 return done;
1484
1485 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001486 /* Clear openssl global errors stack */
1487 ERR_clear_error();
1488
Emeric Brun46591952012-05-18 15:47:34 +02001489 conn->flags |= CO_FL_ERROR;
1490 return done;
1491}
1492
Emeric Brun46591952012-05-18 15:47:34 +02001493static void ssl_sock_close(struct connection *conn) {
1494
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001495 if (conn->xprt_ctx) {
1496 SSL_free(conn->xprt_ctx);
1497 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001498 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001499 }
Emeric Brun46591952012-05-18 15:47:34 +02001500}
1501
1502/* This function tries to perform a clean shutdown on an SSL connection, and in
1503 * any case, flags the connection as reusable if no handshake was in progress.
1504 */
1505static void ssl_sock_shutw(struct connection *conn, int clean)
1506{
1507 if (conn->flags & CO_FL_HANDSHAKE)
1508 return;
1509 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001510 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1511 /* Clear openssl global errors stack */
1512 ERR_clear_error();
1513 }
Emeric Brun46591952012-05-18 15:47:34 +02001514
1515 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001516 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001517}
1518
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001519/* used for logging, may be changed for a sample fetch later */
1520const char *ssl_sock_get_cipher_name(struct connection *conn)
1521{
1522 if (!conn->xprt && !conn->xprt_ctx)
1523 return NULL;
1524 return SSL_get_cipher_name(conn->xprt_ctx);
1525}
1526
1527/* used for logging, may be changed for a sample fetch later */
1528const char *ssl_sock_get_proto_version(struct connection *conn)
1529{
1530 if (!conn->xprt && !conn->xprt_ctx)
1531 return NULL;
1532 return SSL_get_version(conn->xprt_ctx);
1533}
1534
Willy Tarreau8d598402012-10-22 17:58:39 +02001535/* Extract a serial from a cert, and copy it to a chunk.
1536 * Returns 1 if serial is found and copied, 0 if no serial found and
1537 * -1 if output is not large enough.
1538 */
1539static int
1540ssl_sock_get_serial(X509 *crt, struct chunk *out)
1541{
1542 ASN1_INTEGER *serial;
1543
1544 serial = X509_get_serialNumber(crt);
1545 if (!serial)
1546 return 0;
1547
1548 if (out->size < serial->length)
1549 return -1;
1550
1551 memcpy(out->str, serial->data, serial->length);
1552 out->len = serial->length;
1553 return 1;
1554}
1555
Emeric Brunce5ad802012-10-22 14:11:22 +02001556
1557/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1558 * Returns 1 if serial is found and copied, 0 if no valid time found
1559 * and -1 if output is not large enough.
1560 */
1561static int
1562ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1563{
1564 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1565 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1566
1567 if (gentm->length < 12)
1568 return 0;
1569 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1570 return 0;
1571 if (out->size < gentm->length-2)
1572 return -1;
1573
1574 memcpy(out->str, gentm->data+2, gentm->length-2);
1575 out->len = gentm->length-2;
1576 return 1;
1577 }
1578 else if (tm->type == V_ASN1_UTCTIME) {
1579 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1580
1581 if (utctm->length < 10)
1582 return 0;
1583 if (utctm->data[0] >= 0x35)
1584 return 0;
1585 if (out->size < utctm->length)
1586 return -1;
1587
1588 memcpy(out->str, utctm->data, utctm->length);
1589 out->len = utctm->length;
1590 return 1;
1591 }
1592
1593 return 0;
1594}
1595
Emeric Brun87855892012-10-17 17:39:35 +02001596/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1597 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1598 */
1599static int
1600ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1601{
1602 X509_NAME_ENTRY *ne;
1603 int i, j, n;
1604 int cur = 0;
1605 const char *s;
1606 char tmp[128];
1607
1608 out->len = 0;
1609 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1610 if (pos < 0)
1611 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1612 else
1613 j = i;
1614
1615 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1616 n = OBJ_obj2nid(ne->object);
1617 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1618 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1619 s = tmp;
1620 }
1621
1622 if (chunk_strcasecmp(entry, s) != 0)
1623 continue;
1624
1625 if (pos < 0)
1626 cur--;
1627 else
1628 cur++;
1629
1630 if (cur != pos)
1631 continue;
1632
1633 if (ne->value->length > out->size)
1634 return -1;
1635
1636 memcpy(out->str, ne->value->data, ne->value->length);
1637 out->len = ne->value->length;
1638 return 1;
1639 }
1640
1641 return 0;
1642
1643}
1644
1645/* Extract and format full DN from a X509_NAME and copy result into a chunk
1646 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1647 */
1648static int
1649ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1650{
1651 X509_NAME_ENTRY *ne;
1652 int i, n, ln;
1653 int l = 0;
1654 const char *s;
1655 char *p;
1656 char tmp[128];
1657
1658 out->len = 0;
1659 p = out->str;
1660 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1661 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1662 n = OBJ_obj2nid(ne->object);
1663 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1664 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1665 s = tmp;
1666 }
1667 ln = strlen(s);
1668
1669 l += 1 + ln + 1 + ne->value->length;
1670 if (l > out->size)
1671 return -1;
1672 out->len = l;
1673
1674 *(p++)='/';
1675 memcpy(p, s, ln);
1676 p += ln;
1677 *(p++)='=';
1678 memcpy(p, ne->value->data, ne->value->length);
1679 p += ne->value->length;
1680 }
1681
1682 if (!out->len)
1683 return 0;
1684
1685 return 1;
1686}
1687
Willy Tarreau7875d092012-09-10 08:20:03 +02001688/***** Below are some sample fetching functions for ACL/patterns *****/
1689
Emeric Brune64aef12012-09-21 13:15:06 +02001690/* boolean, returns true if client cert was present */
1691static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001692smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001693 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brune64aef12012-09-21 13:15:06 +02001694{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001695 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001696 return 0;
1697
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001698 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001699 smp->flags |= SMP_F_MAY_CHANGE;
1700 return 0;
1701 }
1702
1703 smp->flags = 0;
1704 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001705 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001706
1707 return 1;
1708}
1709
Willy Tarreau8d598402012-10-22 17:58:39 +02001710/* bin, returns serial in a binary chunk */
1711static int
1712smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001713 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02001714{
1715 X509 *crt = NULL;
1716 int ret = 0;
1717 struct chunk *smp_trash;
1718
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001719 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001720 return 0;
1721
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001722 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001723 smp->flags |= SMP_F_MAY_CHANGE;
1724 return 0;
1725 }
1726
1727 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001728 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001729 if (!crt)
1730 goto out;
1731
Willy Tarreau47ca5452012-12-23 20:22:19 +01001732 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001733 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1734 goto out;
1735
1736 smp->data.str = *smp_trash;
1737 smp->type = SMP_T_BIN;
1738 ret = 1;
1739out:
1740 if (crt)
1741 X509_free(crt);
1742 return ret;
1743}
Emeric Brune64aef12012-09-21 13:15:06 +02001744
James Votha051b4a2013-05-14 20:37:59 +02001745/* bin, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk */
1746static int
1747smp_fetch_ssl_c_sha1(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001748 const struct arg *args, struct sample *smp, const char *kw)
James Votha051b4a2013-05-14 20:37:59 +02001749{
1750 X509 *crt = NULL;
1751 const EVP_MD *digest;
1752 int ret = 0;
1753 struct chunk *smp_trash;
1754
1755 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
1756 return 0;
1757
1758 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
1759 smp->flags |= SMP_F_MAY_CHANGE;
1760 return 0;
1761 }
1762
1763 /* SSL_get_peer_certificate, it increase X509 * ref count */
1764 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
1765 if (!crt)
1766 goto out;
1767
1768 smp_trash = get_trash_chunk();
1769 digest = EVP_sha1();
1770 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
1771
1772 smp->data.str = *smp_trash;
1773 smp->type = SMP_T_BIN;
1774 ret = 1;
1775out:
1776 if (crt)
1777 X509_free(crt);
1778 return ret;
1779}
1780
Emeric Brunce5ad802012-10-22 14:11:22 +02001781/*str, returns notafter date in ASN1_UTCTIME format */
1782static int
1783smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001784 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001785{
1786 X509 *crt = NULL;
1787 int ret = 0;
1788 struct chunk *smp_trash;
1789
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001790 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001791 return 0;
1792
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001793 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001794 smp->flags |= SMP_F_MAY_CHANGE;
1795 return 0;
1796 }
1797
1798 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001799 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001800 if (!crt)
1801 goto out;
1802
Willy Tarreau47ca5452012-12-23 20:22:19 +01001803 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001804 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1805 goto out;
1806
1807 smp->data.str = *smp_trash;
1808 smp->type = SMP_T_STR;
1809 ret = 1;
1810out:
1811 if (crt)
1812 X509_free(crt);
1813 return ret;
1814}
1815
Emeric Brun87855892012-10-17 17:39:35 +02001816/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1817static int
1818smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001819 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02001820{
1821 X509 *crt = NULL;
1822 X509_NAME *name;
1823 int ret = 0;
1824 struct chunk *smp_trash;
1825
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001826 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001827 return 0;
1828
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001829 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001830 smp->flags |= SMP_F_MAY_CHANGE;
1831 return 0;
1832 }
1833
1834 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001835 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001836 if (!crt)
1837 goto out;
1838
1839 name = X509_get_issuer_name(crt);
1840 if (!name)
1841 goto out;
1842
Willy Tarreau47ca5452012-12-23 20:22:19 +01001843 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001844 if (args && args[0].type == ARGT_STR) {
1845 int pos = 1;
1846
1847 if (args[1].type == ARGT_SINT)
1848 pos = args[1].data.sint;
1849 else if (args[1].type == ARGT_UINT)
1850 pos =(int)args[1].data.uint;
1851
1852 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1853 goto out;
1854 }
1855 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1856 goto out;
1857
1858 smp->type = SMP_T_STR;
1859 smp->data.str = *smp_trash;
1860 ret = 1;
1861out:
1862 if (crt)
1863 X509_free(crt);
1864 return ret;
1865}
1866
Emeric Brunce5ad802012-10-22 14:11:22 +02001867/*str, returns notbefore date in ASN1_UTCTIME format */
1868static int
1869smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001870 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001871{
1872 X509 *crt = NULL;
1873 int ret = 0;
1874 struct chunk *smp_trash;
1875
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001876 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001877 return 0;
1878
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001879 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001880 smp->flags |= SMP_F_MAY_CHANGE;
1881 return 0;
1882 }
1883
1884 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001885 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001886 if (!crt)
1887 goto out;
1888
Willy Tarreau47ca5452012-12-23 20:22:19 +01001889 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001890 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1891 goto out;
1892
1893 smp->data.str = *smp_trash;
1894 smp->type = SMP_T_STR;
1895 ret = 1;
1896out:
1897 if (crt)
1898 X509_free(crt);
1899 return ret;
1900}
1901
Emeric Brun87855892012-10-17 17:39:35 +02001902/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1903static int
1904smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001905 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02001906{
1907 X509 *crt = NULL;
1908 X509_NAME *name;
1909 int ret = 0;
1910 struct chunk *smp_trash;
1911
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001912 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001913 return 0;
1914
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001915 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001916 smp->flags |= SMP_F_MAY_CHANGE;
1917 return 0;
1918 }
1919
1920 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001921 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001922 if (!crt)
1923 goto out;
1924
1925 name = X509_get_subject_name(crt);
1926 if (!name)
1927 goto out;
1928
Willy Tarreau47ca5452012-12-23 20:22:19 +01001929 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001930 if (args && args[0].type == ARGT_STR) {
1931 int pos = 1;
1932
1933 if (args[1].type == ARGT_SINT)
1934 pos = args[1].data.sint;
1935 else if (args[1].type == ARGT_UINT)
1936 pos =(int)args[1].data.uint;
1937
1938 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1939 goto out;
1940 }
1941 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1942 goto out;
1943
1944 smp->type = SMP_T_STR;
1945 smp->data.str = *smp_trash;
1946 ret = 1;
1947out:
1948 if (crt)
1949 X509_free(crt);
1950 return ret;
1951}
Emeric Brun9143d372012-12-20 15:44:16 +01001952
1953/* integer, returns true if current session use a client certificate */
1954static int
1955smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001956 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun9143d372012-12-20 15:44:16 +01001957{
1958 X509 *crt;
1959
1960 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
1961 return 0;
1962
1963 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
1964 smp->flags |= SMP_F_MAY_CHANGE;
1965 return 0;
1966 }
1967
1968 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
1969 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
1970 if (crt) {
1971 X509_free(crt);
1972 }
1973
1974 smp->type = SMP_T_BOOL;
1975 smp->data.uint = (crt != NULL);
1976 return 1;
1977}
1978
Emeric Bruna7359fd2012-10-17 15:03:11 +02001979/* integer, returns the client certificate version */
1980static int
1981smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001982 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001983{
1984 X509 *crt;
1985
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001986 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001987 return 0;
1988
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001989 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001990 smp->flags |= SMP_F_MAY_CHANGE;
1991 return 0;
1992 }
1993
1994 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001995 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001996 if (!crt)
1997 return 0;
1998
1999 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2000 X509_free(crt);
2001 smp->type = SMP_T_UINT;
2002
2003 return 1;
2004}
2005
Emeric Brun7f56e742012-10-19 18:15:40 +02002006/* str, returns the client certificate sig alg */
2007static int
2008smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002009 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002010{
2011 X509 *crt;
2012 int nid;
2013
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002014 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02002015 return 0;
2016
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002017 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002018 smp->flags |= SMP_F_MAY_CHANGE;
2019 return 0;
2020 }
2021
2022 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002023 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002024 if (!crt)
2025 return 0;
2026
2027 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2028
2029 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2030 if (!smp->data.str.str)
2031 return 0;
2032
2033 smp->type = SMP_T_CSTR;
2034 smp->data.str.len = strlen(smp->data.str.str);
2035 X509_free(crt);
2036
2037 return 1;
2038}
2039
Emeric Brun521a0112012-10-22 12:22:55 +02002040/* str, returns the client certificate key alg */
2041static int
2042smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002043 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002044{
2045 X509 *crt;
2046 int nid;
2047
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002048 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002049 return 0;
2050
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002051 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002052 smp->flags |= SMP_F_MAY_CHANGE;
2053 return 0;
2054 }
2055
2056 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002057 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002058 if (!crt)
2059 return 0;
2060
2061 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2062
2063 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2064 if (!smp->data.str.str)
2065 return 0;
2066
2067 smp->type = SMP_T_CSTR;
2068 smp->data.str.len = strlen(smp->data.str.str);
2069 X509_free(crt);
2070
2071 return 1;
2072}
2073
Emeric Brun2525b6b2012-10-18 15:59:43 +02002074/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02002075static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002076smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002077 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002078{
2079 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002080 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02002081 return 1;
2082}
2083
Emeric Brun2525b6b2012-10-18 15:59:43 +02002084/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02002085static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002086smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002087 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002088{
2089#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2090 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002091 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock) &&
2092 l4->si[0].conn->xprt_ctx &&
2093 SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02002094 return 1;
2095#else
2096 return 0;
2097#endif
2098}
2099
Willy Tarreau8d598402012-10-22 17:58:39 +02002100/* bin, returns serial in a binary chunk */
2101static int
2102smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002103 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02002104{
2105 X509 *crt = NULL;
2106 int ret = 0;
2107 struct chunk *smp_trash;
2108
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002109 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02002110 return 0;
2111
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002112 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02002113 smp->flags |= SMP_F_MAY_CHANGE;
2114 return 0;
2115 }
2116
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002117 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02002118 if (!crt)
2119 goto out;
2120
Willy Tarreau47ca5452012-12-23 20:22:19 +01002121 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02002122 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
2123 goto out;
2124
2125 smp->data.str = *smp_trash;
2126 smp->type = SMP_T_BIN;
2127 ret = 1;
2128out:
2129 return ret;
2130}
Emeric Brunce5ad802012-10-22 14:11:22 +02002131/*str, returns notafter date in ASN1_UTCTIME format */
2132static int
2133smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002134 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002135{
2136 X509 *crt = NULL;
2137 int ret = 0;
2138 struct chunk *smp_trash;
2139
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002140 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02002141 return 0;
2142
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002143 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002144 smp->flags |= SMP_F_MAY_CHANGE;
2145 return 0;
2146 }
2147
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002148 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002149 if (!crt)
2150 goto out;
2151
Willy Tarreau47ca5452012-12-23 20:22:19 +01002152 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002153 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
2154 goto out;
2155
2156 smp->data.str = *smp_trash;
2157 smp->type = SMP_T_STR;
2158 ret = 1;
2159out:
2160 return ret;
2161}
2162
2163/*str, returns notbefore date in ASN1_UTCTIME format */
2164static int
2165smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002166 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002167{
2168 X509 *crt = NULL;
2169 int ret = 0;
2170 struct chunk *smp_trash;
2171
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002172 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02002173 return 0;
2174
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002175 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002176 smp->flags |= SMP_F_MAY_CHANGE;
2177 return 0;
2178 }
2179
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002180 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002181 if (!crt)
2182 goto out;
2183
Willy Tarreau47ca5452012-12-23 20:22:19 +01002184 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002185 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
2186 goto out;
2187
2188 smp->data.str = *smp_trash;
2189 smp->type = SMP_T_STR;
2190 ret = 1;
2191out:
2192 return ret;
2193}
Willy Tarreau8d598402012-10-22 17:58:39 +02002194
Emeric Bruna7359fd2012-10-17 15:03:11 +02002195/* integer, returns the frontend certificate version */
2196static int
2197smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002198 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002199{
2200 X509 *crt;
2201
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002202 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002203 return 0;
2204
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002205 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002206 smp->flags |= SMP_F_MAY_CHANGE;
2207 return 0;
2208 }
2209
2210 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002211 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002212 if (!crt)
2213 return 0;
2214
2215 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2216 smp->type = SMP_T_UINT;
2217
2218 return 1;
2219}
2220
Emeric Brun7f56e742012-10-19 18:15:40 +02002221/* str, returns the client certificate sig alg */
2222static int
2223smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002224 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002225{
2226 X509 *crt;
2227 int nid;
2228
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002229 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02002230 return 0;
2231
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002232 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002233 smp->flags |= SMP_F_MAY_CHANGE;
2234 return 0;
2235 }
2236
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002237 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002238 if (!crt)
2239 return 0;
2240
2241 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2242
2243 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2244 if (!smp->data.str.str)
2245 return 0;
2246
2247 smp->type = SMP_T_CSTR;
2248 smp->data.str.len = strlen(smp->data.str.str);
2249
2250 return 1;
2251}
2252
Emeric Brun521a0112012-10-22 12:22:55 +02002253/* str, returns the client certificate key alg */
2254static int
2255smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002256 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002257{
2258 X509 *crt;
2259 int nid;
2260
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002261 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002262 return 0;
2263
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002264 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002265 smp->flags |= SMP_F_MAY_CHANGE;
2266 return 0;
2267 }
2268
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002269 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002270 if (!crt)
2271 return 0;
2272
2273 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2274
2275 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2276 if (!smp->data.str.str)
2277 return 0;
2278
2279 smp->type = SMP_T_CSTR;
2280 smp->data.str.len = strlen(smp->data.str.str);
2281
2282 return 1;
2283}
2284
Emeric Brun87855892012-10-17 17:39:35 +02002285/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2286static int
2287smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002288 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002289{
2290 X509 *crt = NULL;
2291 X509_NAME *name;
2292 int ret = 0;
2293 struct chunk *smp_trash;
2294
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002295 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002296 return 0;
2297
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002298 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002299 smp->flags |= SMP_F_MAY_CHANGE;
2300 return 0;
2301 }
2302
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002303 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002304 if (!crt)
2305 goto out;
2306
2307 name = X509_get_issuer_name(crt);
2308 if (!name)
2309 goto out;
2310
Willy Tarreau47ca5452012-12-23 20:22:19 +01002311 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002312 if (args && args[0].type == ARGT_STR) {
2313 int pos = 1;
2314
2315 if (args[1].type == ARGT_SINT)
2316 pos = args[1].data.sint;
2317 else if (args[1].type == ARGT_UINT)
2318 pos =(int)args[1].data.uint;
2319
2320 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2321 goto out;
2322 }
2323 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2324 goto out;
2325
2326 smp->type = SMP_T_STR;
2327 smp->data.str = *smp_trash;
2328 ret = 1;
2329out:
2330 return ret;
2331}
2332
2333/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2334static int
2335smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002336 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002337{
2338 X509 *crt = NULL;
2339 X509_NAME *name;
2340 int ret = 0;
2341 struct chunk *smp_trash;
2342
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002343 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002344 return 0;
2345
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002346 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002347 smp->flags |= SMP_F_MAY_CHANGE;
2348 return 0;
2349 }
2350
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002351 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002352 if (!crt)
2353 goto out;
2354
2355 name = X509_get_subject_name(crt);
2356 if (!name)
2357 goto out;
2358
Willy Tarreau47ca5452012-12-23 20:22:19 +01002359 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002360 if (args && args[0].type == ARGT_STR) {
2361 int pos = 1;
2362
2363 if (args[1].type == ARGT_SINT)
2364 pos = args[1].data.sint;
2365 else if (args[1].type == ARGT_UINT)
2366 pos =(int)args[1].data.uint;
2367
2368 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2369 goto out;
2370 }
2371 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2372 goto out;
2373
2374 smp->type = SMP_T_STR;
2375 smp->data.str = *smp_trash;
2376 ret = 1;
2377out:
2378 return ret;
2379}
2380
Emeric Brun589fcad2012-10-16 14:13:26 +02002381static int
2382smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002383 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002384{
2385 smp->flags = 0;
2386
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002387 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002388 return 0;
2389
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002390 smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002391 if (!smp->data.str.str)
2392 return 0;
2393
2394 smp->type = SMP_T_CSTR;
2395 smp->data.str.len = strlen(smp->data.str.str);
2396
2397 return 1;
2398}
2399
2400static int
2401smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002402 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002403{
2404 smp->flags = 0;
2405
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002406 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002407 return 0;
2408
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002409 if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
Emeric Brun589fcad2012-10-16 14:13:26 +02002410 return 0;
2411
2412 smp->type = SMP_T_UINT;
2413
2414 return 1;
2415}
2416
2417static int
2418smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002419 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002420{
2421 smp->flags = 0;
2422
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002423 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002424 return 0;
2425
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002426 smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002427 if (!smp->data.uint)
2428 return 0;
2429
2430 smp->type = SMP_T_UINT;
2431
2432 return 1;
2433}
2434
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002435#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002436static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002437smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002438 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002439{
Willy Tarreaua33c6542012-10-15 13:19:06 +02002440 smp->flags = 0;
2441 smp->type = SMP_T_CSTR;
2442
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002443 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002444 return 0;
2445
2446 smp->data.str.str = NULL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002447 SSL_get0_next_proto_negotiated(l4->si[0].conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002448 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2449
2450 if (!smp->data.str.str)
2451 return 0;
2452
2453 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002454}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002455#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002456
Willy Tarreauab861d32013-04-02 02:30:41 +02002457#ifdef OPENSSL_ALPN_NEGOTIATED
2458static int
2459smp_fetch_ssl_fc_alpn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002460 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreauab861d32013-04-02 02:30:41 +02002461{
2462 smp->flags = 0;
2463 smp->type = SMP_T_CSTR;
2464
2465 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
2466 return 0;
2467
2468 smp->data.str.str = NULL;
2469 SSL_get0_alpn_negotiated(l4->si[0].conn->xprt_ctx,
2470 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2471
2472 if (!smp->data.str.str)
2473 return 0;
2474
2475 return 1;
2476}
2477#endif
2478
Willy Tarreaua33c6542012-10-15 13:19:06 +02002479static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002480smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002481 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002482{
2483 smp->flags = 0;
2484
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002485 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002486 return 0;
2487
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002488 smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002489 if (!smp->data.str.str)
2490 return 0;
2491
2492 smp->type = SMP_T_CSTR;
2493 smp->data.str.len = strlen(smp->data.str.str);
2494
2495 return 1;
2496}
2497
2498static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002499smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002500 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunfe68f682012-10-16 14:59:28 +02002501{
2502#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2503 SSL_SESSION *sess;
2504
2505 smp->flags = 0;
2506 smp->type = SMP_T_CBIN;
2507
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002508 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunfe68f682012-10-16 14:59:28 +02002509 return 0;
2510
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002511 sess = SSL_get_session(l4->si[0].conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002512 if (!sess)
2513 return 0;
2514
2515 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2516 if (!smp->data.str.str || !&smp->data.str.len)
2517 return 0;
2518
2519 return 1;
2520#else
2521 return 0;
2522#endif
2523}
2524
2525static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002526smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002527 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002528{
2529#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2530 smp->flags = 0;
2531 smp->type = SMP_T_CSTR;
2532
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002533 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau7875d092012-09-10 08:20:03 +02002534 return 0;
2535
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002536 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 +02002537 if (!smp->data.str.str)
2538 return 0;
2539
Willy Tarreau7875d092012-09-10 08:20:03 +02002540 smp->data.str.len = strlen(smp->data.str.str);
2541 return 1;
2542#else
2543 return 0;
2544#endif
2545}
2546
Emeric Brun2525b6b2012-10-18 15:59:43 +02002547/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002548static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002549smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002550 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002551{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002552 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002553 return 0;
2554
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002555 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002556 smp->flags = SMP_F_MAY_CHANGE;
2557 return 0;
2558 }
2559
2560 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002561 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002562 smp->flags = 0;
2563
2564 return 1;
2565}
2566
Emeric Brun2525b6b2012-10-18 15:59:43 +02002567/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002568static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002569smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002570 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002571{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002572 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002573 return 0;
2574
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002575 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002576 smp->flags = SMP_F_MAY_CHANGE;
2577 return 0;
2578 }
2579
2580 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002581 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002582 smp->flags = 0;
2583
2584 return 1;
2585}
2586
Emeric Brun2525b6b2012-10-18 15:59:43 +02002587/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002588static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002589smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002590 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002591{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002592 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002593 return 0;
2594
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002595 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002596 smp->flags = SMP_F_MAY_CHANGE;
2597 return 0;
2598 }
2599
2600 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002601 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002602 smp->flags = 0;
2603
2604 return 1;
2605}
2606
Emeric Brun2525b6b2012-10-18 15:59:43 +02002607/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002608static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002609smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002610 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002611{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002612 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002613 return 0;
2614
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002615 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002616 smp->flags = SMP_F_MAY_CHANGE;
2617 return 0;
2618 }
2619
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002620 if (!l4->si[0].conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002621 return 0;
2622
2623 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002624 smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002625 smp->flags = 0;
2626
2627 return 1;
2628}
2629
Emeric Brunfb510ea2012-10-05 12:00:26 +02002630/* parse the "ca-file" bind keyword */
2631static 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 +02002632{
2633 if (!*args[cur_arg + 1]) {
2634 if (err)
2635 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2636 return ERR_ALERT | ERR_FATAL;
2637 }
2638
Emeric Brunef42d922012-10-11 16:11:36 +02002639 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2640 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2641 else
2642 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002643
Emeric Brund94b3fe2012-09-20 18:23:56 +02002644 return 0;
2645}
2646
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002647/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002648static 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 +02002649{
2650 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002651 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002652 return ERR_ALERT | ERR_FATAL;
2653 }
2654
Emeric Brun76d88952012-10-05 15:47:31 +02002655 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002656 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002657 return 0;
2658}
2659
2660/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002661static 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 +02002662{
Willy Tarreau38011032013-08-13 16:59:39 +02002663 char path[MAXPATHLEN];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002664 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002665 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002666 return ERR_ALERT | ERR_FATAL;
2667 }
2668
Emeric Brunc8e8d122012-10-02 18:42:10 +02002669 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
Willy Tarreau38011032013-08-13 16:59:39 +02002670 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02002671 memprintf(err, "'%s' : path too long", args[cur_arg]);
2672 return ERR_ALERT | ERR_FATAL;
2673 }
2674 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2675 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2676 return ERR_ALERT | ERR_FATAL;
2677
2678 return 0;
2679 }
2680
Willy Tarreau4348fad2012-09-20 16:48:07 +02002681 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002682 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002683
2684 return 0;
2685}
2686
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002687/* parse the "crt-list" bind keyword */
2688static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2689{
2690 if (!*args[cur_arg + 1]) {
2691 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
2692 return ERR_ALERT | ERR_FATAL;
2693 }
2694
Willy Tarreauad1731d2013-04-02 17:35:58 +02002695 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
2696 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002697 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02002698 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002699
2700 return 0;
2701}
2702
Emeric Brunfb510ea2012-10-05 12:00:26 +02002703/* parse the "crl-file" bind keyword */
2704static 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 +02002705{
Emeric Brun051cdab2012-10-02 19:25:50 +02002706#ifndef X509_V_FLAG_CRL_CHECK
2707 if (err)
2708 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2709 return ERR_ALERT | ERR_FATAL;
2710#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002711 if (!*args[cur_arg + 1]) {
2712 if (err)
2713 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2714 return ERR_ALERT | ERR_FATAL;
2715 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002716
Emeric Brunef42d922012-10-11 16:11:36 +02002717 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2718 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2719 else
2720 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002721
Emeric Brun2b58d042012-09-20 17:10:03 +02002722 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002723#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002724}
2725
2726/* parse the "ecdhe" bind keyword keywords */
2727static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2728{
2729#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2730 if (err)
2731 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2732 return ERR_ALERT | ERR_FATAL;
2733#elif defined(OPENSSL_NO_ECDH)
2734 if (err)
2735 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2736 return ERR_ALERT | ERR_FATAL;
2737#else
2738 if (!*args[cur_arg + 1]) {
2739 if (err)
2740 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2741 return ERR_ALERT | ERR_FATAL;
2742 }
2743
2744 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002745
2746 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002747#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002748}
2749
Emeric Brun81c00f02012-09-21 14:31:21 +02002750/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2751static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2752{
2753 int code;
2754 char *p = args[cur_arg + 1];
2755 unsigned long long *ignerr = &conf->crt_ignerr;
2756
2757 if (!*p) {
2758 if (err)
2759 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2760 return ERR_ALERT | ERR_FATAL;
2761 }
2762
2763 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2764 ignerr = &conf->ca_ignerr;
2765
2766 if (strcmp(p, "all") == 0) {
2767 *ignerr = ~0ULL;
2768 return 0;
2769 }
2770
2771 while (p) {
2772 code = atoi(p);
2773 if ((code <= 0) || (code > 63)) {
2774 if (err)
2775 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2776 args[cur_arg], code, args[cur_arg + 1]);
2777 return ERR_ALERT | ERR_FATAL;
2778 }
2779 *ignerr |= 1ULL << code;
2780 p = strchr(p, ',');
2781 if (p)
2782 p++;
2783 }
2784
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002785 return 0;
2786}
2787
2788/* parse the "force-sslv3" bind keyword */
2789static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2790{
2791 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2792 return 0;
2793}
2794
2795/* parse the "force-tlsv10" bind keyword */
2796static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2797{
2798 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002799 return 0;
2800}
2801
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002802/* parse the "force-tlsv11" bind keyword */
2803static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2804{
2805#if SSL_OP_NO_TLSv1_1
2806 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
2807 return 0;
2808#else
2809 if (err)
2810 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
2811 return ERR_ALERT | ERR_FATAL;
2812#endif
2813}
2814
2815/* parse the "force-tlsv12" bind keyword */
2816static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2817{
2818#if SSL_OP_NO_TLSv1_2
2819 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
2820 return 0;
2821#else
2822 if (err)
2823 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
2824 return ERR_ALERT | ERR_FATAL;
2825#endif
2826}
2827
2828
Emeric Brun2d0c4822012-10-02 13:45:20 +02002829/* parse the "no-tls-tickets" bind keyword */
2830static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2831{
Emeric Brun89675492012-10-05 13:48:26 +02002832 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02002833 return 0;
2834}
2835
Emeric Brun2d0c4822012-10-02 13:45:20 +02002836
Emeric Brun9b3009b2012-10-05 11:55:06 +02002837/* parse the "no-sslv3" bind keyword */
2838static 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 +02002839{
Emeric Brun89675492012-10-05 13:48:26 +02002840 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002841 return 0;
2842}
2843
Emeric Brun9b3009b2012-10-05 11:55:06 +02002844/* parse the "no-tlsv10" bind keyword */
2845static 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 +02002846{
Emeric Brun89675492012-10-05 13:48:26 +02002847 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002848 return 0;
2849}
2850
Emeric Brun9b3009b2012-10-05 11:55:06 +02002851/* parse the "no-tlsv11" bind keyword */
2852static 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 +02002853{
Emeric Brun89675492012-10-05 13:48:26 +02002854 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002855 return 0;
2856}
2857
Emeric Brun9b3009b2012-10-05 11:55:06 +02002858/* parse the "no-tlsv12" bind keyword */
2859static 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 +02002860{
Emeric Brun89675492012-10-05 13:48:26 +02002861 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002862 return 0;
2863}
2864
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002865/* parse the "npn" bind keyword */
2866static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2867{
2868#ifdef OPENSSL_NPN_NEGOTIATED
2869 char *p1, *p2;
2870
2871 if (!*args[cur_arg + 1]) {
2872 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
2873 return ERR_ALERT | ERR_FATAL;
2874 }
2875
2876 free(conf->npn_str);
2877
2878 /* the NPN string is built as a suite of (<len> <name>)* */
2879 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
2880 conf->npn_str = calloc(1, conf->npn_len);
2881 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
2882
2883 /* replace commas with the name length */
2884 p1 = conf->npn_str;
2885 p2 = p1 + 1;
2886 while (1) {
2887 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
2888 if (!p2)
2889 p2 = p1 + 1 + strlen(p1 + 1);
2890
2891 if (p2 - (p1 + 1) > 255) {
2892 *p2 = '\0';
2893 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2894 return ERR_ALERT | ERR_FATAL;
2895 }
2896
2897 *p1 = p2 - (p1 + 1);
2898 p1 = p2;
2899
2900 if (!*p2)
2901 break;
2902
2903 *(p2++) = '\0';
2904 }
2905 return 0;
2906#else
2907 if (err)
2908 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
2909 return ERR_ALERT | ERR_FATAL;
2910#endif
2911}
2912
Willy Tarreauab861d32013-04-02 02:30:41 +02002913/* parse the "alpn" bind keyword */
2914static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2915{
2916#ifdef OPENSSL_ALPN_NEGOTIATED
2917 char *p1, *p2;
2918
2919 if (!*args[cur_arg + 1]) {
2920 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
2921 return ERR_ALERT | ERR_FATAL;
2922 }
2923
2924 free(conf->alpn_str);
2925
2926 /* the ALPN string is built as a suite of (<len> <name>)* */
2927 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
2928 conf->alpn_str = calloc(1, conf->alpn_len);
2929 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
2930
2931 /* replace commas with the name length */
2932 p1 = conf->alpn_str;
2933 p2 = p1 + 1;
2934 while (1) {
2935 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
2936 if (!p2)
2937 p2 = p1 + 1 + strlen(p1 + 1);
2938
2939 if (p2 - (p1 + 1) > 255) {
2940 *p2 = '\0';
2941 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2942 return ERR_ALERT | ERR_FATAL;
2943 }
2944
2945 *p1 = p2 - (p1 + 1);
2946 p1 = p2;
2947
2948 if (!*p2)
2949 break;
2950
2951 *(p2++) = '\0';
2952 }
2953 return 0;
2954#else
2955 if (err)
2956 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
2957 return ERR_ALERT | ERR_FATAL;
2958#endif
2959}
2960
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002961/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002962static 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 +02002963{
Willy Tarreau81796be2012-09-22 19:11:47 +02002964 struct listener *l;
2965
Willy Tarreau4348fad2012-09-20 16:48:07 +02002966 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02002967
2968 if (global.listen_default_ciphers && !conf->ciphers)
2969 conf->ciphers = strdup(global.listen_default_ciphers);
2970
Willy Tarreau81796be2012-09-22 19:11:47 +02002971 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002972 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02002973
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002974 return 0;
2975}
2976
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002977/* parse the "strict-sni" bind keyword */
2978static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2979{
2980 conf->strict_sni = 1;
2981 return 0;
2982}
2983
Emeric Brund94b3fe2012-09-20 18:23:56 +02002984/* parse the "verify" bind keyword */
2985static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2986{
2987 if (!*args[cur_arg + 1]) {
2988 if (err)
2989 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
2990 return ERR_ALERT | ERR_FATAL;
2991 }
2992
2993 if (strcmp(args[cur_arg + 1], "none") == 0)
2994 conf->verify = SSL_VERIFY_NONE;
2995 else if (strcmp(args[cur_arg + 1], "optional") == 0)
2996 conf->verify = SSL_VERIFY_PEER;
2997 else if (strcmp(args[cur_arg + 1], "required") == 0)
2998 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2999 else {
3000 if (err)
3001 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
3002 args[cur_arg], args[cur_arg + 1]);
3003 return ERR_ALERT | ERR_FATAL;
3004 }
3005
3006 return 0;
3007}
3008
Willy Tarreau92faadf2012-10-10 23:04:25 +02003009/************** "server" keywords ****************/
3010
Emeric Brunef42d922012-10-11 16:11:36 +02003011/* parse the "ca-file" server keyword */
3012static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3013{
3014 if (!*args[*cur_arg + 1]) {
3015 if (err)
3016 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
3017 return ERR_ALERT | ERR_FATAL;
3018 }
3019
3020 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3021 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3022 else
3023 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
3024
3025 return 0;
3026}
3027
Willy Tarreau92faadf2012-10-10 23:04:25 +02003028/* parse the "check-ssl" server keyword */
3029static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3030{
3031 newsrv->check.use_ssl = 1;
3032 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3033 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3034 return 0;
3035}
3036
3037/* parse the "ciphers" server keyword */
3038static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3039{
3040 if (!*args[*cur_arg + 1]) {
3041 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
3042 return ERR_ALERT | ERR_FATAL;
3043 }
3044
3045 free(newsrv->ssl_ctx.ciphers);
3046 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
3047 return 0;
3048}
3049
Emeric Brunef42d922012-10-11 16:11:36 +02003050/* parse the "crl-file" server keyword */
3051static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3052{
3053#ifndef X509_V_FLAG_CRL_CHECK
3054 if (err)
3055 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
3056 return ERR_ALERT | ERR_FATAL;
3057#else
3058 if (!*args[*cur_arg + 1]) {
3059 if (err)
3060 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
3061 return ERR_ALERT | ERR_FATAL;
3062 }
3063
3064 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3065 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3066 else
3067 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
3068
3069 return 0;
3070#endif
3071}
3072
Emeric Bruna7aa3092012-10-26 12:58:00 +02003073/* parse the "crt" server keyword */
3074static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3075{
3076 if (!*args[*cur_arg + 1]) {
3077 if (err)
3078 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
3079 return ERR_ALERT | ERR_FATAL;
3080 }
3081
3082 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
3083 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3084 else
3085 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
3086
3087 return 0;
3088}
Emeric Brunef42d922012-10-11 16:11:36 +02003089
Willy Tarreau92faadf2012-10-10 23:04:25 +02003090/* parse the "force-sslv3" server keyword */
3091static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3092{
3093 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
3094 return 0;
3095}
3096
3097/* parse the "force-tlsv10" server keyword */
3098static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3099{
3100 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
3101 return 0;
3102}
3103
3104/* parse the "force-tlsv11" server keyword */
3105static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3106{
3107#if SSL_OP_NO_TLSv1_1
3108 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
3109 return 0;
3110#else
3111 if (err)
3112 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
3113 return ERR_ALERT | ERR_FATAL;
3114#endif
3115}
3116
3117/* parse the "force-tlsv12" server keyword */
3118static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3119{
3120#if SSL_OP_NO_TLSv1_2
3121 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
3122 return 0;
3123#else
3124 if (err)
3125 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
3126 return ERR_ALERT | ERR_FATAL;
3127#endif
3128}
3129
3130/* parse the "no-sslv3" server keyword */
3131static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3132{
3133 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
3134 return 0;
3135}
3136
3137/* parse the "no-tlsv10" server keyword */
3138static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3139{
3140 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
3141 return 0;
3142}
3143
3144/* parse the "no-tlsv11" server keyword */
3145static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3146{
3147 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
3148 return 0;
3149}
3150
3151/* parse the "no-tlsv12" server keyword */
3152static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3153{
3154 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
3155 return 0;
3156}
3157
Emeric Brunf9c5c472012-10-11 15:28:34 +02003158/* parse the "no-tls-tickets" server keyword */
3159static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3160{
3161 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
3162 return 0;
3163}
3164
Willy Tarreau92faadf2012-10-10 23:04:25 +02003165/* parse the "ssl" server keyword */
3166static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3167{
3168 newsrv->use_ssl = 1;
3169 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3170 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3171 return 0;
3172}
3173
Emeric Brunef42d922012-10-11 16:11:36 +02003174/* parse the "verify" server keyword */
3175static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3176{
3177 if (!*args[*cur_arg + 1]) {
3178 if (err)
3179 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
3180 return ERR_ALERT | ERR_FATAL;
3181 }
3182
3183 if (strcmp(args[*cur_arg + 1], "none") == 0)
3184 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
3185 else if (strcmp(args[*cur_arg + 1], "required") == 0)
3186 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
3187 else {
3188 if (err)
3189 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
3190 args[*cur_arg], args[*cur_arg + 1]);
3191 return ERR_ALERT | ERR_FATAL;
3192 }
3193
Evan Broderbe554312013-06-27 00:05:25 -07003194 return 0;
3195}
3196
3197/* parse the "verifyhost" server keyword */
3198static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3199{
3200 if (!*args[*cur_arg + 1]) {
3201 if (err)
3202 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
3203 return ERR_ALERT | ERR_FATAL;
3204 }
3205
3206 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
3207
Emeric Brunef42d922012-10-11 16:11:36 +02003208 return 0;
3209}
3210
Willy Tarreau7875d092012-09-10 08:20:03 +02003211/* Note: must not be declared <const> as its list will be overwritten.
3212 * Please take care of keeping this list alphabetically sorted.
3213 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003214static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Willy Tarreau80aca902013-01-07 15:42:20 +01003215 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3216 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3217 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3218 { "ssl_c_i_dn", smp_fetch_ssl_c_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3219 { "ssl_c_key_alg", smp_fetch_ssl_c_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3220 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3221 { "ssl_c_notbefore", smp_fetch_ssl_c_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3222 { "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3223 { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3224 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
James Votha051b4a2013-05-14 20:37:59 +02003225 { "ssl_c_sha1", smp_fetch_ssl_c_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01003226 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3227 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3228 { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3229 { "ssl_f_i_dn", smp_fetch_ssl_f_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3230 { "ssl_f_key_alg", smp_fetch_ssl_f_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3231 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3232 { "ssl_f_notbefore", smp_fetch_ssl_f_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3233 { "ssl_f_sig_alg", smp_fetch_ssl_f_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3234 { "ssl_f_s_dn", smp_fetch_ssl_f_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3235 { "ssl_f_serial", smp_fetch_ssl_f_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3236 { "ssl_f_version", smp_fetch_ssl_f_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3237 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3238 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3239 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3240 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3241 { "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 +02003242#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau80aca902013-01-07 15:42:20 +01003243 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003244#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003245#ifdef OPENSSL_ALPN_NEGOTIATED
3246 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3247#endif
Willy Tarreau80aca902013-01-07 15:42:20 +01003248 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3249 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3250 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_CBIN, SMP_USE_L5CLI },
3251 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreau7875d092012-09-10 08:20:03 +02003252 { NULL, NULL, 0, 0, 0 },
3253}};
3254
3255/* Note: must not be declared <const> as its list will be overwritten.
3256 * Please take care of keeping this list alphabetically sorted.
3257 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003258static struct acl_kw_list acl_kws = {ILH, {
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003259 { "ssl_c_i_dn", NULL, acl_parse_str, acl_match_str },
3260 { "ssl_c_key_alg", NULL, acl_parse_str, acl_match_str },
3261 { "ssl_c_notafter", NULL, acl_parse_str, acl_match_str },
3262 { "ssl_c_notbefore", NULL, acl_parse_str, acl_match_str },
3263 { "ssl_c_sig_alg", NULL, acl_parse_str, acl_match_str },
3264 { "ssl_c_s_dn", NULL, acl_parse_str, acl_match_str },
3265 { "ssl_c_serial", NULL, acl_parse_bin, acl_match_bin },
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003266 { "ssl_f_i_dn", NULL, acl_parse_str, acl_match_str },
3267 { "ssl_f_key_alg", NULL, acl_parse_str, acl_match_str },
3268 { "ssl_f_notafter", NULL, acl_parse_str, acl_match_str },
3269 { "ssl_f_notbefore", NULL, acl_parse_str, acl_match_str },
3270 { "ssl_f_sig_alg", NULL, acl_parse_str, acl_match_str },
3271 { "ssl_f_s_dn", NULL, acl_parse_str, acl_match_str },
3272 { "ssl_f_serial", NULL, acl_parse_bin, acl_match_bin },
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003273 { "ssl_fc_cipher", NULL, acl_parse_str, acl_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003274#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003275 { "ssl_fc_npn", NULL, acl_parse_str, acl_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003276#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003277#ifdef OPENSSL_ALPN_NEGOTIATED
3278 { "ssl_fc_alpn", NULL, acl_parse_str, acl_match_str },
3279#endif
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003280 { "ssl_fc_protocol", NULL, acl_parse_str, acl_match_str },
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003281 { "ssl_fc_sni", "ssl_fc_sni", acl_parse_str, acl_match_str },
3282 { "ssl_fc_sni_end", "ssl_fc_sni", acl_parse_str, acl_match_end },
3283 { "ssl_fc_sni_reg", "ssl_fc_sni", acl_parse_reg, acl_match_reg },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01003284 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02003285}};
3286
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003287/* Note: must not be declared <const> as its list will be overwritten.
3288 * Please take care of keeping this list alphabetically sorted, doing so helps
3289 * all code contributors.
3290 * Optional keywords are also declared with a NULL ->parse() function so that
3291 * the config parser can report an appropriate error when a known keyword was
3292 * not enabled.
3293 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02003294static struct bind_kw_list bind_kws = { "SSL", { }, {
Willy Tarreauab861d32013-04-02 02:30:41 +02003295 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003296 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003297 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
3298 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003299 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003300 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
3301 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003302 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003303 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003304 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
3305 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
3306 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
3307 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02003308 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
3309 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
3310 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
3311 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003312 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003313 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003314 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003315 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003316 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003317 { NULL, NULL, 0 },
3318}};
Emeric Brun46591952012-05-18 15:47:34 +02003319
Willy Tarreau92faadf2012-10-10 23:04:25 +02003320/* Note: must not be declared <const> as its list will be overwritten.
3321 * Please take care of keeping this list alphabetically sorted, doing so helps
3322 * all code contributors.
3323 * Optional keywords are also declared with a NULL ->parse() function so that
3324 * the config parser can report an appropriate error when a known keyword was
3325 * not enabled.
3326 */
3327static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02003328 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003329 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
3330 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02003331 { "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 +02003332 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003333 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
3334 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
3335 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
3336 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
3337 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
3338 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
3339 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
3340 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02003341 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003342 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02003343 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Evan Broderbe554312013-06-27 00:05:25 -07003344 { "verifyhost", srv_parse_verifyhost, 1, 0 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02003345 { NULL, NULL, 0, 0 },
3346}};
3347
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003348/* transport-layer operations for SSL sockets */
3349struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02003350 .snd_buf = ssl_sock_from_buf,
3351 .rcv_buf = ssl_sock_to_buf,
3352 .rcv_pipe = NULL,
3353 .snd_pipe = NULL,
3354 .shutr = NULL,
3355 .shutw = ssl_sock_shutw,
3356 .close = ssl_sock_close,
3357 .init = ssl_sock_init,
3358};
3359
3360__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02003361static void __ssl_sock_init(void)
3362{
Emeric Brun46591952012-05-18 15:47:34 +02003363 STACK_OF(SSL_COMP)* cm;
3364
3365 SSL_library_init();
3366 cm = SSL_COMP_get_compression_methods();
3367 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02003368 sample_register_fetches(&sample_fetch_keywords);
3369 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003370 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02003371 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02003372}
3373
3374/*
3375 * Local variables:
3376 * c-indent-level: 8
3377 * c-basic-offset: 8
3378 * End:
3379 */