blob: ce1712d4f28ae98c46c108ca75523e7b1081fc2f [file] [log] [blame]
Emeric Brun46591952012-05-18 15:47:34 +02001/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02003 *
4 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
Willy Tarreau69845df2012-09-10 09:43:09 +020011 * Acknowledgement:
12 * We'd like to specially thank the Stud project authors for a very clean
13 * and well documented code which helped us understand how the OpenSSL API
14 * ought to be used in non-blocking mode. This is one difficult part which
15 * is not easy to get from the OpenSSL doc, and reading the Stud code made
16 * it much more obvious than the examples in the OpenSSL package. Keep up
17 * the good works, guys !
18 *
19 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
20 * particularly well with haproxy. For more info about this project, visit :
21 * https://github.com/bumptech/stud
22 *
Emeric Brun46591952012-05-18 15:47:34 +020023 */
24
25#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020026#include <ctype.h>
27#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020028#include <errno.h>
29#include <fcntl.h>
30#include <stdio.h>
31#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020032#include <string.h>
33#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020034
35#include <sys/socket.h>
36#include <sys/stat.h>
37#include <sys/types.h>
38
39#include <netinet/tcp.h>
40
41#include <openssl/ssl.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020042#include <openssl/x509.h>
43#include <openssl/x509v3.h>
44#include <openssl/x509.h>
45#include <openssl/err.h>
Thierry Fournier383085f2013-01-24 14:15:43 +010046#include <openssl/rand.h>
Emeric Brun46591952012-05-18 15:47:34 +020047
48#include <common/buffer.h>
49#include <common/compat.h>
50#include <common/config.h>
51#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020052#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020053#include <common/standard.h>
54#include <common/ticks.h>
55#include <common/time.h>
56
Emeric Brunfc0421f2012-09-07 17:30:07 +020057#include <ebsttree.h>
58
59#include <types/global.h>
60#include <types/ssl_sock.h>
61
Willy Tarreau7875d092012-09-10 08:20:03 +020062#include <proto/acl.h>
63#include <proto/arg.h>
Emeric Brun46591952012-05-18 15:47:34 +020064#include <proto/connection.h>
65#include <proto/fd.h>
66#include <proto/freq_ctr.h>
67#include <proto/frontend.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020068#include <proto/listener.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020069#include <proto/server.h>
Emeric Brun46591952012-05-18 15:47:34 +020070#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +020071#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020072#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +020073#include <proto/ssl_sock.h>
74#include <proto/task.h>
75
Emeric Brune64aef12012-09-21 13:15:06 +020076#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brunf282a812012-09-21 15:27:54 +020077/* bits 0xFFFF0000 are reserved to store verify errors */
78
79/* Verify errors macros */
80#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
81#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
82#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
83
84#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
85#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
86#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +020087
Willy Tarreau403edff2012-09-06 11:58:37 +020088static int sslconns = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +020089
90void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
91{
92 struct connection *conn = (struct connection *)SSL_get_app_data(ssl);
93 (void)ret; /* shut gcc stupid warning */
94
95 if (where & SSL_CB_HANDSHAKE_START) {
96 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreau20879a02012-12-03 16:32:10 +010097 if (conn->flags & CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +020098 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +010099 conn->err_code = CO_ER_SSL_RENEG;
100 }
Emeric Brune1f38db2012-09-03 20:36:47 +0200101 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200102}
103
Emeric Brune64aef12012-09-21 13:15:06 +0200104/* Callback is called for each certificate of the chain during a verify
105 ok is set to 1 if preverify detect no error on current certificate.
106 Returns 0 to break the handshake, 1 otherwise. */
107int ssl_sock_verifycbk(int ok, X509_STORE_CTX *x_store)
108{
109 SSL *ssl;
110 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +0200111 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +0200112
113 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
114 conn = (struct connection *)SSL_get_app_data(ssl);
115
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200116 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +0200117
Emeric Brun81c00f02012-09-21 14:31:21 +0200118 if (ok) /* no errors */
119 return ok;
120
121 depth = X509_STORE_CTX_get_error_depth(x_store);
122 err = X509_STORE_CTX_get_error(x_store);
123
124 /* check if CA error needs to be ignored */
125 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200126 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
127 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
128 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +0200129 }
130
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100131 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
132 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +0200133 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100134 }
Emeric Brun81c00f02012-09-21 14:31:21 +0200135
Willy Tarreau20879a02012-12-03 16:32:10 +0100136 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +0200137 return 0;
138 }
139
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200140 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
141 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +0200142
Emeric Brun81c00f02012-09-21 14:31:21 +0200143 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100144 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
145 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +0200146 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100147 }
Emeric Brun81c00f02012-09-21 14:31:21 +0200148
Willy Tarreau20879a02012-12-03 16:32:10 +0100149 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +0200150 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +0200151}
152
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200153#ifdef OPENSSL_NPN_NEGOTIATED
154/* This callback is used so that the server advertises the list of
155 * negociable protocols for NPN.
156 */
157static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
158 unsigned int *len, void *arg)
159{
160 struct bind_conf *conf = arg;
161
162 *data = (const unsigned char *)conf->npn_str;
163 *len = conf->npn_len;
164 return SSL_TLSEXT_ERR_OK;
165}
166#endif
167
Willy Tarreauab861d32013-04-02 02:30:41 +0200168#ifdef OPENSSL_ALPN_NEGOTIATED
169/* This callback is used so that the server advertises the list of
170 * negociable protocols for ALPN.
171 */
172static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **data,
173 unsigned int *len, void *arg)
174{
175 struct bind_conf *conf = arg;
176
177 *data = (const unsigned char *)conf->alpn_str;
178 *len = conf->alpn_len;
179 return SSL_TLSEXT_ERR_OK;
180}
181#endif
182
Emeric Brunfc0421f2012-09-07 17:30:07 +0200183#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
184/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
185 * warning when no match is found, which implies the default (first) cert
186 * will keep being used.
187 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200188static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, struct bind_conf *s)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200189{
190 const char *servername;
191 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200192 struct ebmb_node *node, *n;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200193 int i;
194 (void)al; /* shut gcc stupid warning */
195
196 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100197 if (!servername) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200198 return (s->strict_sni ?
199 SSL_TLSEXT_ERR_ALERT_FATAL :
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);
Emeric Brune64aef12012-09-21 13:15:06 +0200696 SSL_CTX_set_verify(ctx, bind_conf->verify ? bind_conf->verify : SSL_VERIFY_NONE, ssl_sock_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
Emeric Brun94324a42012-10-11 14:00:19 +0200772/* prepare ssl context from servers options. Returns an error count */
773int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
774{
775 int cfgerr = 0;
776 int options =
777 SSL_OP_ALL | /* all known workarounds for bugs */
778 SSL_OP_NO_SSLv2 |
779 SSL_OP_NO_COMPRESSION;
780 int mode =
781 SSL_MODE_ENABLE_PARTIAL_WRITE |
782 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
783 SSL_MODE_RELEASE_BUFFERS;
784
Thierry Fournier383085f2013-01-24 14:15:43 +0100785 /* Make sure openssl opens /dev/urandom before the chroot */
786 if (!ssl_initialize_random()) {
787 Alert("OpenSSL random data generator initialization failed.\n");
788 cfgerr++;
789 }
790
Emeric Brun94324a42012-10-11 14:00:19 +0200791 /* Initiate SSL context for current server */
792 srv->ssl_ctx.reused_sess = NULL;
793 if (srv->use_ssl)
794 srv->xprt = &ssl_sock;
795 if (srv->check.use_ssl)
796 srv->check.xprt = &ssl_sock;
797
798 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
799 if (!srv->ssl_ctx.ctx) {
800 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
801 proxy_type_str(curproxy), curproxy->id,
802 srv->id);
803 cfgerr++;
804 return cfgerr;
805 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200806 if (srv->ssl_ctx.client_crt) {
807 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
808 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
809 proxy_type_str(curproxy), curproxy->id,
810 srv->id, srv->ssl_ctx.client_crt);
811 cfgerr++;
812 }
813 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
814 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
815 proxy_type_str(curproxy), curproxy->id,
816 srv->id, srv->ssl_ctx.client_crt);
817 cfgerr++;
818 }
819 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
820 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
821 proxy_type_str(curproxy), curproxy->id,
822 srv->id, srv->ssl_ctx.client_crt);
823 cfgerr++;
824 }
825 }
Emeric Brun94324a42012-10-11 14:00:19 +0200826
827 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
828 options |= SSL_OP_NO_SSLv3;
829 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
830 options |= SSL_OP_NO_TLSv1;
831 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
832 options |= SSL_OP_NO_TLSv1_1;
833 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
834 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200835 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
836 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200837 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
838 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
839 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
840 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
841#if SSL_OP_NO_TLSv1_1
842 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
843 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
844#endif
845#if SSL_OP_NO_TLSv1_2
846 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
847 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
848#endif
849
850 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
851 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Emeric Brunef42d922012-10-11 16:11:36 +0200852 SSL_CTX_set_verify(srv->ssl_ctx.ctx, srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE, NULL);
853 if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
854 if (srv->ssl_ctx.ca_file) {
855 /* load CAfile to verify */
856 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
857 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
858 curproxy->id, srv->id,
859 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
860 cfgerr++;
861 }
862 }
863#ifdef X509_V_FLAG_CRL_CHECK
864 if (srv->ssl_ctx.crl_file) {
865 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
866
867 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
868 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
869 curproxy->id, srv->id,
870 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
871 cfgerr++;
872 }
873 else {
874 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
875 }
876 }
877#endif
878 }
879
Emeric Brun4f65bff2012-11-16 15:11:00 +0100880 if (global.tune.ssllifetime)
881 SSL_CTX_set_timeout(srv->ssl_ctx.ctx, global.tune.ssllifetime);
882
Emeric Brun94324a42012-10-11 14:00:19 +0200883 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
884 if (srv->ssl_ctx.ciphers &&
885 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
886 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
887 curproxy->id, srv->id,
888 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
889 cfgerr++;
890 }
891
892 return cfgerr;
893}
894
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200895/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200896 * be NULL, in which case nothing is done. Returns the number of errors
897 * encountered.
898 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200899int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200900{
901 struct ebmb_node *node;
902 struct sni_ctx *sni;
903 int err = 0;
904
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200905 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200906 return 0;
907
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200908 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200909 while (node) {
910 sni = ebmb_entry(node, struct sni_ctx, name);
911 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200912 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200913 node = ebmb_next(node);
914 }
915
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200916 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200917 while (node) {
918 sni = ebmb_entry(node, struct sni_ctx, name);
919 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200920 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200921 node = ebmb_next(node);
922 }
923 return err;
924}
925
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200926/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200927 * be NULL, in which case nothing is done. The default_ctx is nullified too.
928 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200929void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200930{
931 struct ebmb_node *node, *back;
932 struct sni_ctx *sni;
933
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200934 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200935 return;
936
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200937 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200938 while (node) {
939 sni = ebmb_entry(node, struct sni_ctx, name);
940 back = ebmb_next(node);
941 ebmb_delete(node);
942 if (!sni->order) /* only free the CTX on its first occurrence */
943 SSL_CTX_free(sni->ctx);
944 free(sni);
945 node = back;
946 }
947
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200948 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200949 while (node) {
950 sni = ebmb_entry(node, struct sni_ctx, name);
951 back = ebmb_next(node);
952 ebmb_delete(node);
953 if (!sni->order) /* only free the CTX on its first occurrence */
954 SSL_CTX_free(sni->ctx);
955 free(sni);
956 node = back;
957 }
958
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200959 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +0200960}
961
Emeric Brun46591952012-05-18 15:47:34 +0200962/*
963 * This function is called if SSL * context is not yet allocated. The function
964 * is designed to be called before any other data-layer operation and sets the
965 * handshake flag on the connection. It is safe to call it multiple times.
966 * It returns 0 on success and -1 in error case.
967 */
968static int ssl_sock_init(struct connection *conn)
969{
970 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200971 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200972 return 0;
973
Willy Tarreau20879a02012-12-03 16:32:10 +0100974 if (global.maxsslconn && sslconns >= global.maxsslconn) {
975 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +0200976 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100977 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200978
Emeric Brun46591952012-05-18 15:47:34 +0200979 /* If it is in client mode initiate SSL session
980 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100981 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200982 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100983 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +0100984 if (!conn->xprt_ctx) {
985 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +0200986 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100987 }
Emeric Brun46591952012-05-18 15:47:34 +0200988
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200989 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100990 if (objt_server(conn->target)->ssl_ctx.reused_sess)
991 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +0200992
993 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200994 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200995
996 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200997 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200998
999 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001000 return 0;
1001 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001002 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001003 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001004 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001005 if (!conn->xprt_ctx) {
1006 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001007 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001008 }
Emeric Brun46591952012-05-18 15:47:34 +02001009
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001010 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001011
1012 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001013 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001014
Emeric Brune1f38db2012-09-03 20:36:47 +02001015 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001016 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +02001017
Emeric Brun46591952012-05-18 15:47:34 +02001018 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001019 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001020
1021 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001022 return 0;
1023 }
1024 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01001025 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02001026 return -1;
1027}
1028
1029
1030/* This is the callback which is used when an SSL handshake is pending. It
1031 * updates the FD status if it wants some polling before being called again.
1032 * It returns 0 if it fails in a fatal way or needs to poll to go further,
1033 * otherwise it returns non-zero and removes itself from the connection's
1034 * flags (the bit is provided in <flag> by the caller).
1035 */
1036int ssl_sock_handshake(struct connection *conn, unsigned int flag)
1037{
1038 int ret;
1039
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001040 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001041 goto out_error;
1042
Emeric Brun674b7432012-11-08 19:21:55 +01001043 /* If we use SSL_do_handshake to process a reneg initiated by
1044 * the remote peer, it sometimes returns SSL_ERROR_SSL.
1045 * Usually SSL_write and SSL_read are used and process implicitly
1046 * the reneg handshake.
1047 * Here we use SSL_peek as a workaround for reneg.
1048 */
1049 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
1050 char c;
1051
1052 ret = SSL_peek(conn->xprt_ctx, &c, 1);
1053 if (ret <= 0) {
1054 /* handshake may have not been completed, let's find why */
1055 ret = SSL_get_error(conn->xprt_ctx, ret);
1056 if (ret == SSL_ERROR_WANT_WRITE) {
1057 /* SSL handshake needs to write, L4 connection may not be ready */
1058 __conn_sock_stop_recv(conn);
1059 __conn_sock_poll_send(conn);
1060 return 0;
1061 }
1062 else if (ret == SSL_ERROR_WANT_READ) {
1063 /* handshake may have been completed but we have
1064 * no more data to read.
1065 */
1066 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
1067 ret = 1;
1068 goto reneg_ok;
1069 }
1070 /* SSL handshake needs to read, L4 connection is ready */
1071 if (conn->flags & CO_FL_WAIT_L4_CONN)
1072 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1073 __conn_sock_stop_send(conn);
1074 __conn_sock_poll_recv(conn);
1075 return 0;
1076 }
1077 else if (ret == SSL_ERROR_SYSCALL) {
1078 /* if errno is null, then connection was successfully established */
1079 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1080 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001081 if (!conn->err_code) {
1082 if (!((SSL *)conn->xprt_ctx)->packet_length)
1083 if (!errno)
1084 conn->err_code = CO_ER_SSL_EMPTY;
1085 else
1086 conn->err_code = CO_ER_SSL_ABORT;
1087 else
1088 conn->err_code = CO_ER_SSL_HANDSHAKE;
1089 }
Emeric Brun674b7432012-11-08 19:21:55 +01001090 goto out_error;
1091 }
1092 else {
1093 /* Fail on all other handshake errors */
1094 /* Note: OpenSSL may leave unread bytes in the socket's
1095 * buffer, causing an RST to be emitted upon close() on
1096 * TCP sockets. We first try to drain possibly pending
1097 * data to avoid this as much as possible.
1098 */
Willy Tarreau2b57cb82013-06-10 19:56:38 +02001099 if (conn->ctrl && conn->ctrl->drain)
1100 conn->ctrl->drain(conn->t.sock.fd);
Willy Tarreau20879a02012-12-03 16:32:10 +01001101 if (!conn->err_code)
1102 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01001103 goto out_error;
1104 }
1105 }
1106 /* read some data: consider handshake completed */
1107 goto reneg_ok;
1108 }
1109
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001110 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001111 if (ret != 1) {
1112 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001113 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001114
1115 if (ret == SSL_ERROR_WANT_WRITE) {
1116 /* SSL handshake needs to write, L4 connection may not be ready */
1117 __conn_sock_stop_recv(conn);
1118 __conn_sock_poll_send(conn);
1119 return 0;
1120 }
1121 else if (ret == SSL_ERROR_WANT_READ) {
1122 /* SSL handshake needs to read, L4 connection is ready */
1123 if (conn->flags & CO_FL_WAIT_L4_CONN)
1124 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1125 __conn_sock_stop_send(conn);
1126 __conn_sock_poll_recv(conn);
1127 return 0;
1128 }
Willy Tarreau89230192012-09-28 20:22:13 +02001129 else if (ret == SSL_ERROR_SYSCALL) {
1130 /* if errno is null, then connection was successfully established */
1131 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1132 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001133
1134 if (!((SSL *)conn->xprt_ctx)->packet_length)
1135 if (!errno)
1136 conn->err_code = CO_ER_SSL_EMPTY;
1137 else
1138 conn->err_code = CO_ER_SSL_ABORT;
1139 else
1140 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +02001141 goto out_error;
1142 }
Emeric Brun46591952012-05-18 15:47:34 +02001143 else {
1144 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02001145 /* Note: OpenSSL may leave unread bytes in the socket's
1146 * buffer, causing an RST to be emitted upon close() on
1147 * TCP sockets. We first try to drain possibly pending
1148 * data to avoid this as much as possible.
1149 */
Willy Tarreau2b57cb82013-06-10 19:56:38 +02001150 if (conn->ctrl && conn->ctrl->drain)
1151 conn->ctrl->drain(conn->t.sock.fd);
Willy Tarreau20879a02012-12-03 16:32:10 +01001152 if (!conn->err_code)
1153 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001154 goto out_error;
1155 }
1156 }
1157
Emeric Brun674b7432012-11-08 19:21:55 +01001158reneg_ok:
1159
Emeric Brun46591952012-05-18 15:47:34 +02001160 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001161 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001162 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +02001163 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001164 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1165 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001166
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001167 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001168 }
1169 }
1170
1171 /* The connection is now established at both layers, it's time to leave */
1172 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1173 return 1;
1174
1175 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001176 /* Clear openssl global errors stack */
1177 ERR_clear_error();
1178
Emeric Brun9fa89732012-10-04 17:09:56 +02001179 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001180 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1181 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1182 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001183 }
1184
Emeric Brun46591952012-05-18 15:47:34 +02001185 /* Fail on all other handshake errors */
1186 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001187 if (!conn->err_code)
1188 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001189 return 0;
1190}
1191
1192/* Receive up to <count> bytes from connection <conn>'s socket and store them
1193 * into buffer <buf>. The caller must ensure that <count> is always smaller
1194 * than the buffer's size. Only one call to recv() is performed, unless the
1195 * buffer wraps, in which case a second call may be performed. The connection's
1196 * flags are updated with whatever special event is detected (error, read0,
1197 * empty). The caller is responsible for taking care of those events and
1198 * avoiding the call if inappropriate. The function does not call the
1199 * connection's polling update function, so the caller is responsible for this.
1200 */
1201static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1202{
1203 int ret, done = 0;
1204 int try = count;
1205
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001206 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001207 goto out_error;
1208
1209 if (conn->flags & CO_FL_HANDSHAKE)
1210 /* a handshake was requested */
1211 return 0;
1212
1213 /* compute the maximum block size we can read at once. */
1214 if (buffer_empty(buf)) {
1215 /* let's realign the buffer to optimize I/O */
1216 buf->p = buf->data;
1217 }
1218 else if (buf->data + buf->o < buf->p &&
1219 buf->p + buf->i < buf->data + buf->size) {
1220 /* remaining space wraps at the end, with a moving limit */
1221 if (try > buf->data + buf->size - (buf->p + buf->i))
1222 try = buf->data + buf->size - (buf->p + buf->i);
1223 }
1224
1225 /* read the largest possible block. For this, we perform only one call
1226 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1227 * in which case we accept to do it once again. A new attempt is made on
1228 * EINTR too.
1229 */
1230 while (try) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001231 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001232 if (conn->flags & CO_FL_ERROR) {
1233 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001234 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001235 }
Emeric Brun46591952012-05-18 15:47:34 +02001236 if (ret > 0) {
1237 buf->i += ret;
1238 done += ret;
1239 if (ret < try)
1240 break;
1241 count -= ret;
1242 try = count;
1243 }
1244 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001245 ret = SSL_get_error(conn->xprt_ctx, ret);
1246 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001247 /* error on protocol or underlying transport */
1248 if ((ret != SSL_ERROR_SYSCALL)
1249 || (errno && (errno != EAGAIN)))
1250 conn->flags |= CO_FL_ERROR;
1251
Emeric Brun644cde02012-12-14 11:21:13 +01001252 /* Clear openssl global errors stack */
1253 ERR_clear_error();
1254 }
Emeric Brun46591952012-05-18 15:47:34 +02001255 goto read0;
1256 }
1257 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001258 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001259 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001260 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001261 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001262 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001263 break;
1264 }
1265 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001266 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1267 /* handshake is running, and it may need to re-enable read */
1268 conn->flags |= CO_FL_SSL_WAIT_HS;
1269 __conn_sock_want_recv(conn);
1270 break;
1271 }
Emeric Brun46591952012-05-18 15:47:34 +02001272 /* we need to poll for retry a read later */
1273 __conn_data_poll_recv(conn);
1274 break;
1275 }
1276 /* otherwise it's a real error */
1277 goto out_error;
1278 }
1279 }
1280 return done;
1281
1282 read0:
1283 conn_sock_read0(conn);
1284 return done;
1285 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001286 /* Clear openssl global errors stack */
1287 ERR_clear_error();
1288
Emeric Brun46591952012-05-18 15:47:34 +02001289 conn->flags |= CO_FL_ERROR;
1290 return done;
1291}
1292
1293
1294/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1295 * <flags> may contain MSG_MORE to make the system hold on without sending
1296 * data too fast, but this flag is ignored at the moment.
1297 * Only one call to send() is performed, unless the buffer wraps, in which case
1298 * a second call may be performed. The connection's flags are updated with
1299 * whatever special event is detected (error, empty). The caller is responsible
1300 * for taking care of those events and avoiding the call if inappropriate. The
1301 * function does not call the connection's polling update function, so the caller
1302 * is responsible for this.
1303 */
1304static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1305{
1306 int ret, try, done;
1307
1308 done = 0;
1309
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001310 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001311 goto out_error;
1312
1313 if (conn->flags & CO_FL_HANDSHAKE)
1314 /* a handshake was requested */
1315 return 0;
1316
1317 /* send the largest possible block. For this we perform only one call
1318 * to send() unless the buffer wraps and we exactly fill the first hunk,
1319 * in which case we accept to do it once again.
1320 */
1321 while (buf->o) {
Kevin Hestercad82342013-05-30 15:12:41 -07001322 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01001323
1324 if (global.tune.ssl_max_record && try > global.tune.ssl_max_record)
1325 try = global.tune.ssl_max_record;
1326
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001327 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001328 if (conn->flags & CO_FL_ERROR) {
1329 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001330 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001331 }
Emeric Brun46591952012-05-18 15:47:34 +02001332 if (ret > 0) {
1333 buf->o -= ret;
1334 done += ret;
1335
Willy Tarreau5fb38032012-12-16 19:39:09 +01001336 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001337 /* optimize data alignment in the buffer */
1338 buf->p = buf->data;
1339
1340 /* if the system buffer is full, don't insist */
1341 if (ret < try)
1342 break;
1343 }
1344 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001345 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001346 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001347 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1348 /* handshake is running, and it may need to re-enable write */
1349 conn->flags |= CO_FL_SSL_WAIT_HS;
1350 __conn_sock_want_send(conn);
1351 break;
1352 }
Emeric Brun46591952012-05-18 15:47:34 +02001353 /* we need to poll to retry a write later */
1354 __conn_data_poll_send(conn);
1355 break;
1356 }
1357 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001358 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001359 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001360 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001361 break;
1362 }
1363 goto out_error;
1364 }
1365 }
1366 return done;
1367
1368 out_error:
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 conn->flags |= CO_FL_ERROR;
1373 return done;
1374}
1375
Emeric Brun46591952012-05-18 15:47:34 +02001376static void ssl_sock_close(struct connection *conn) {
1377
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001378 if (conn->xprt_ctx) {
1379 SSL_free(conn->xprt_ctx);
1380 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001381 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001382 }
Emeric Brun46591952012-05-18 15:47:34 +02001383}
1384
1385/* This function tries to perform a clean shutdown on an SSL connection, and in
1386 * any case, flags the connection as reusable if no handshake was in progress.
1387 */
1388static void ssl_sock_shutw(struct connection *conn, int clean)
1389{
1390 if (conn->flags & CO_FL_HANDSHAKE)
1391 return;
1392 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001393 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1394 /* Clear openssl global errors stack */
1395 ERR_clear_error();
1396 }
Emeric Brun46591952012-05-18 15:47:34 +02001397
1398 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001399 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001400}
1401
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001402/* used for logging, may be changed for a sample fetch later */
1403const char *ssl_sock_get_cipher_name(struct connection *conn)
1404{
1405 if (!conn->xprt && !conn->xprt_ctx)
1406 return NULL;
1407 return SSL_get_cipher_name(conn->xprt_ctx);
1408}
1409
1410/* used for logging, may be changed for a sample fetch later */
1411const char *ssl_sock_get_proto_version(struct connection *conn)
1412{
1413 if (!conn->xprt && !conn->xprt_ctx)
1414 return NULL;
1415 return SSL_get_version(conn->xprt_ctx);
1416}
1417
Willy Tarreau8d598402012-10-22 17:58:39 +02001418/* Extract a serial from a cert, and copy it to a chunk.
1419 * Returns 1 if serial is found and copied, 0 if no serial found and
1420 * -1 if output is not large enough.
1421 */
1422static int
1423ssl_sock_get_serial(X509 *crt, struct chunk *out)
1424{
1425 ASN1_INTEGER *serial;
1426
1427 serial = X509_get_serialNumber(crt);
1428 if (!serial)
1429 return 0;
1430
1431 if (out->size < serial->length)
1432 return -1;
1433
1434 memcpy(out->str, serial->data, serial->length);
1435 out->len = serial->length;
1436 return 1;
1437}
1438
Emeric Brunce5ad802012-10-22 14:11:22 +02001439
1440/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1441 * Returns 1 if serial is found and copied, 0 if no valid time found
1442 * and -1 if output is not large enough.
1443 */
1444static int
1445ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1446{
1447 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1448 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1449
1450 if (gentm->length < 12)
1451 return 0;
1452 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1453 return 0;
1454 if (out->size < gentm->length-2)
1455 return -1;
1456
1457 memcpy(out->str, gentm->data+2, gentm->length-2);
1458 out->len = gentm->length-2;
1459 return 1;
1460 }
1461 else if (tm->type == V_ASN1_UTCTIME) {
1462 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1463
1464 if (utctm->length < 10)
1465 return 0;
1466 if (utctm->data[0] >= 0x35)
1467 return 0;
1468 if (out->size < utctm->length)
1469 return -1;
1470
1471 memcpy(out->str, utctm->data, utctm->length);
1472 out->len = utctm->length;
1473 return 1;
1474 }
1475
1476 return 0;
1477}
1478
Emeric Brun87855892012-10-17 17:39:35 +02001479/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1480 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1481 */
1482static int
1483ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1484{
1485 X509_NAME_ENTRY *ne;
1486 int i, j, n;
1487 int cur = 0;
1488 const char *s;
1489 char tmp[128];
1490
1491 out->len = 0;
1492 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1493 if (pos < 0)
1494 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1495 else
1496 j = i;
1497
1498 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1499 n = OBJ_obj2nid(ne->object);
1500 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1501 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1502 s = tmp;
1503 }
1504
1505 if (chunk_strcasecmp(entry, s) != 0)
1506 continue;
1507
1508 if (pos < 0)
1509 cur--;
1510 else
1511 cur++;
1512
1513 if (cur != pos)
1514 continue;
1515
1516 if (ne->value->length > out->size)
1517 return -1;
1518
1519 memcpy(out->str, ne->value->data, ne->value->length);
1520 out->len = ne->value->length;
1521 return 1;
1522 }
1523
1524 return 0;
1525
1526}
1527
1528/* Extract and format full DN from a X509_NAME and copy result into a chunk
1529 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1530 */
1531static int
1532ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1533{
1534 X509_NAME_ENTRY *ne;
1535 int i, n, ln;
1536 int l = 0;
1537 const char *s;
1538 char *p;
1539 char tmp[128];
1540
1541 out->len = 0;
1542 p = out->str;
1543 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1544 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1545 n = OBJ_obj2nid(ne->object);
1546 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1547 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1548 s = tmp;
1549 }
1550 ln = strlen(s);
1551
1552 l += 1 + ln + 1 + ne->value->length;
1553 if (l > out->size)
1554 return -1;
1555 out->len = l;
1556
1557 *(p++)='/';
1558 memcpy(p, s, ln);
1559 p += ln;
1560 *(p++)='=';
1561 memcpy(p, ne->value->data, ne->value->length);
1562 p += ne->value->length;
1563 }
1564
1565 if (!out->len)
1566 return 0;
1567
1568 return 1;
1569}
1570
Willy Tarreau7875d092012-09-10 08:20:03 +02001571/***** Below are some sample fetching functions for ACL/patterns *****/
1572
Emeric Brune64aef12012-09-21 13:15:06 +02001573/* boolean, returns true if client cert was present */
1574static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001575smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001576 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brune64aef12012-09-21 13:15:06 +02001577{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001578 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001579 return 0;
1580
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001581 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001582 smp->flags |= SMP_F_MAY_CHANGE;
1583 return 0;
1584 }
1585
1586 smp->flags = 0;
1587 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001588 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001589
1590 return 1;
1591}
1592
Willy Tarreau8d598402012-10-22 17:58:39 +02001593/* bin, returns serial in a binary chunk */
1594static int
1595smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001596 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02001597{
1598 X509 *crt = NULL;
1599 int ret = 0;
1600 struct chunk *smp_trash;
1601
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001602 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001603 return 0;
1604
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001605 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001606 smp->flags |= SMP_F_MAY_CHANGE;
1607 return 0;
1608 }
1609
1610 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001611 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001612 if (!crt)
1613 goto out;
1614
Willy Tarreau47ca5452012-12-23 20:22:19 +01001615 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001616 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1617 goto out;
1618
1619 smp->data.str = *smp_trash;
1620 smp->type = SMP_T_BIN;
1621 ret = 1;
1622out:
1623 if (crt)
1624 X509_free(crt);
1625 return ret;
1626}
Emeric Brune64aef12012-09-21 13:15:06 +02001627
James Votha051b4a2013-05-14 20:37:59 +02001628/* bin, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk */
1629static int
1630smp_fetch_ssl_c_sha1(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001631 const struct arg *args, struct sample *smp, const char *kw)
James Votha051b4a2013-05-14 20:37:59 +02001632{
1633 X509 *crt = NULL;
1634 const EVP_MD *digest;
1635 int ret = 0;
1636 struct chunk *smp_trash;
1637
1638 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
1639 return 0;
1640
1641 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
1642 smp->flags |= SMP_F_MAY_CHANGE;
1643 return 0;
1644 }
1645
1646 /* SSL_get_peer_certificate, it increase X509 * ref count */
1647 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
1648 if (!crt)
1649 goto out;
1650
1651 smp_trash = get_trash_chunk();
1652 digest = EVP_sha1();
1653 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
1654
1655 smp->data.str = *smp_trash;
1656 smp->type = SMP_T_BIN;
1657 ret = 1;
1658out:
1659 if (crt)
1660 X509_free(crt);
1661 return ret;
1662}
1663
Emeric Brunce5ad802012-10-22 14:11:22 +02001664/*str, returns notafter date in ASN1_UTCTIME format */
1665static int
1666smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001667 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001668{
1669 X509 *crt = NULL;
1670 int ret = 0;
1671 struct chunk *smp_trash;
1672
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001673 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001674 return 0;
1675
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001676 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001677 smp->flags |= SMP_F_MAY_CHANGE;
1678 return 0;
1679 }
1680
1681 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001682 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001683 if (!crt)
1684 goto out;
1685
Willy Tarreau47ca5452012-12-23 20:22:19 +01001686 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001687 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1688 goto out;
1689
1690 smp->data.str = *smp_trash;
1691 smp->type = SMP_T_STR;
1692 ret = 1;
1693out:
1694 if (crt)
1695 X509_free(crt);
1696 return ret;
1697}
1698
Emeric Brun87855892012-10-17 17:39:35 +02001699/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1700static int
1701smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001702 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02001703{
1704 X509 *crt = NULL;
1705 X509_NAME *name;
1706 int ret = 0;
1707 struct chunk *smp_trash;
1708
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001709 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001710 return 0;
1711
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001712 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001713 smp->flags |= SMP_F_MAY_CHANGE;
1714 return 0;
1715 }
1716
1717 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001718 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001719 if (!crt)
1720 goto out;
1721
1722 name = X509_get_issuer_name(crt);
1723 if (!name)
1724 goto out;
1725
Willy Tarreau47ca5452012-12-23 20:22:19 +01001726 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001727 if (args && args[0].type == ARGT_STR) {
1728 int pos = 1;
1729
1730 if (args[1].type == ARGT_SINT)
1731 pos = args[1].data.sint;
1732 else if (args[1].type == ARGT_UINT)
1733 pos =(int)args[1].data.uint;
1734
1735 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1736 goto out;
1737 }
1738 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1739 goto out;
1740
1741 smp->type = SMP_T_STR;
1742 smp->data.str = *smp_trash;
1743 ret = 1;
1744out:
1745 if (crt)
1746 X509_free(crt);
1747 return ret;
1748}
1749
Emeric Brunce5ad802012-10-22 14:11:22 +02001750/*str, returns notbefore date in ASN1_UTCTIME format */
1751static int
1752smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001753 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001754{
1755 X509 *crt = NULL;
1756 int ret = 0;
1757 struct chunk *smp_trash;
1758
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001759 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001760 return 0;
1761
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001762 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001763 smp->flags |= SMP_F_MAY_CHANGE;
1764 return 0;
1765 }
1766
1767 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001768 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001769 if (!crt)
1770 goto out;
1771
Willy Tarreau47ca5452012-12-23 20:22:19 +01001772 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001773 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1774 goto out;
1775
1776 smp->data.str = *smp_trash;
1777 smp->type = SMP_T_STR;
1778 ret = 1;
1779out:
1780 if (crt)
1781 X509_free(crt);
1782 return ret;
1783}
1784
Emeric Brun87855892012-10-17 17:39:35 +02001785/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1786static int
1787smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001788 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02001789{
1790 X509 *crt = NULL;
1791 X509_NAME *name;
1792 int ret = 0;
1793 struct chunk *smp_trash;
1794
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001795 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001796 return 0;
1797
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001798 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001799 smp->flags |= SMP_F_MAY_CHANGE;
1800 return 0;
1801 }
1802
1803 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001804 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001805 if (!crt)
1806 goto out;
1807
1808 name = X509_get_subject_name(crt);
1809 if (!name)
1810 goto out;
1811
Willy Tarreau47ca5452012-12-23 20:22:19 +01001812 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001813 if (args && args[0].type == ARGT_STR) {
1814 int pos = 1;
1815
1816 if (args[1].type == ARGT_SINT)
1817 pos = args[1].data.sint;
1818 else if (args[1].type == ARGT_UINT)
1819 pos =(int)args[1].data.uint;
1820
1821 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1822 goto out;
1823 }
1824 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1825 goto out;
1826
1827 smp->type = SMP_T_STR;
1828 smp->data.str = *smp_trash;
1829 ret = 1;
1830out:
1831 if (crt)
1832 X509_free(crt);
1833 return ret;
1834}
Emeric Brun9143d372012-12-20 15:44:16 +01001835
1836/* integer, returns true if current session use a client certificate */
1837static int
1838smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001839 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun9143d372012-12-20 15:44:16 +01001840{
1841 X509 *crt;
1842
1843 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
1844 return 0;
1845
1846 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
1847 smp->flags |= SMP_F_MAY_CHANGE;
1848 return 0;
1849 }
1850
1851 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
1852 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
1853 if (crt) {
1854 X509_free(crt);
1855 }
1856
1857 smp->type = SMP_T_BOOL;
1858 smp->data.uint = (crt != NULL);
1859 return 1;
1860}
1861
Emeric Bruna7359fd2012-10-17 15:03:11 +02001862/* integer, returns the client certificate version */
1863static int
1864smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001865 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001866{
1867 X509 *crt;
1868
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001869 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001870 return 0;
1871
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001872 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001873 smp->flags |= SMP_F_MAY_CHANGE;
1874 return 0;
1875 }
1876
1877 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001878 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001879 if (!crt)
1880 return 0;
1881
1882 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1883 X509_free(crt);
1884 smp->type = SMP_T_UINT;
1885
1886 return 1;
1887}
1888
Emeric Brun7f56e742012-10-19 18:15:40 +02001889/* str, returns the client certificate sig alg */
1890static int
1891smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001892 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02001893{
1894 X509 *crt;
1895 int nid;
1896
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001897 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02001898 return 0;
1899
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001900 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02001901 smp->flags |= SMP_F_MAY_CHANGE;
1902 return 0;
1903 }
1904
1905 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001906 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02001907 if (!crt)
1908 return 0;
1909
1910 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1911
1912 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1913 if (!smp->data.str.str)
1914 return 0;
1915
1916 smp->type = SMP_T_CSTR;
1917 smp->data.str.len = strlen(smp->data.str.str);
1918 X509_free(crt);
1919
1920 return 1;
1921}
1922
Emeric Brun521a0112012-10-22 12:22:55 +02001923/* str, returns the client certificate key alg */
1924static int
1925smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001926 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02001927{
1928 X509 *crt;
1929 int nid;
1930
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001931 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02001932 return 0;
1933
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001934 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02001935 smp->flags |= SMP_F_MAY_CHANGE;
1936 return 0;
1937 }
1938
1939 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001940 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02001941 if (!crt)
1942 return 0;
1943
1944 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1945
1946 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1947 if (!smp->data.str.str)
1948 return 0;
1949
1950 smp->type = SMP_T_CSTR;
1951 smp->data.str.len = strlen(smp->data.str.str);
1952 X509_free(crt);
1953
1954 return 1;
1955}
1956
Emeric Brun2525b6b2012-10-18 15:59:43 +02001957/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02001958static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001959smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001960 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02001961{
1962 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001963 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02001964 return 1;
1965}
1966
Emeric Brun2525b6b2012-10-18 15:59:43 +02001967/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02001968static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001969smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001970 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02001971{
1972#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1973 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001974 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock) &&
1975 l4->si[0].conn->xprt_ctx &&
1976 SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02001977 return 1;
1978#else
1979 return 0;
1980#endif
1981}
1982
Willy Tarreau8d598402012-10-22 17:58:39 +02001983/* bin, returns serial in a binary chunk */
1984static int
1985smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001986 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02001987{
1988 X509 *crt = NULL;
1989 int ret = 0;
1990 struct chunk *smp_trash;
1991
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001992 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001993 return 0;
1994
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001995 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001996 smp->flags |= SMP_F_MAY_CHANGE;
1997 return 0;
1998 }
1999
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002000 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02002001 if (!crt)
2002 goto out;
2003
Willy Tarreau47ca5452012-12-23 20:22:19 +01002004 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02002005 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
2006 goto out;
2007
2008 smp->data.str = *smp_trash;
2009 smp->type = SMP_T_BIN;
2010 ret = 1;
2011out:
2012 return ret;
2013}
Emeric Brunce5ad802012-10-22 14:11:22 +02002014/*str, returns notafter date in ASN1_UTCTIME format */
2015static int
2016smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002017 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002018{
2019 X509 *crt = NULL;
2020 int ret = 0;
2021 struct chunk *smp_trash;
2022
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002023 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02002024 return 0;
2025
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002026 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002027 smp->flags |= SMP_F_MAY_CHANGE;
2028 return 0;
2029 }
2030
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002031 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002032 if (!crt)
2033 goto out;
2034
Willy Tarreau47ca5452012-12-23 20:22:19 +01002035 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002036 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
2037 goto out;
2038
2039 smp->data.str = *smp_trash;
2040 smp->type = SMP_T_STR;
2041 ret = 1;
2042out:
2043 return ret;
2044}
2045
2046/*str, returns notbefore date in ASN1_UTCTIME format */
2047static int
2048smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002049 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002050{
2051 X509 *crt = NULL;
2052 int ret = 0;
2053 struct chunk *smp_trash;
2054
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002055 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02002056 return 0;
2057
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002058 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002059 smp->flags |= SMP_F_MAY_CHANGE;
2060 return 0;
2061 }
2062
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002063 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002064 if (!crt)
2065 goto out;
2066
Willy Tarreau47ca5452012-12-23 20:22:19 +01002067 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002068 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
2069 goto out;
2070
2071 smp->data.str = *smp_trash;
2072 smp->type = SMP_T_STR;
2073 ret = 1;
2074out:
2075 return ret;
2076}
Willy Tarreau8d598402012-10-22 17:58:39 +02002077
Emeric Bruna7359fd2012-10-17 15:03:11 +02002078/* integer, returns the frontend certificate version */
2079static int
2080smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002081 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002082{
2083 X509 *crt;
2084
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002085 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002086 return 0;
2087
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002088 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002089 smp->flags |= SMP_F_MAY_CHANGE;
2090 return 0;
2091 }
2092
2093 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002094 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002095 if (!crt)
2096 return 0;
2097
2098 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2099 smp->type = SMP_T_UINT;
2100
2101 return 1;
2102}
2103
Emeric Brun7f56e742012-10-19 18:15:40 +02002104/* str, returns the client certificate sig alg */
2105static int
2106smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002107 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002108{
2109 X509 *crt;
2110 int nid;
2111
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002112 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02002113 return 0;
2114
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002115 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002116 smp->flags |= SMP_F_MAY_CHANGE;
2117 return 0;
2118 }
2119
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002120 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002121 if (!crt)
2122 return 0;
2123
2124 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2125
2126 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2127 if (!smp->data.str.str)
2128 return 0;
2129
2130 smp->type = SMP_T_CSTR;
2131 smp->data.str.len = strlen(smp->data.str.str);
2132
2133 return 1;
2134}
2135
Emeric Brun521a0112012-10-22 12:22:55 +02002136/* str, returns the client certificate key alg */
2137static int
2138smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002139 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002140{
2141 X509 *crt;
2142 int nid;
2143
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002144 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002145 return 0;
2146
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002147 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002148 smp->flags |= SMP_F_MAY_CHANGE;
2149 return 0;
2150 }
2151
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002152 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002153 if (!crt)
2154 return 0;
2155
2156 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2157
2158 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2159 if (!smp->data.str.str)
2160 return 0;
2161
2162 smp->type = SMP_T_CSTR;
2163 smp->data.str.len = strlen(smp->data.str.str);
2164
2165 return 1;
2166}
2167
Emeric Brun87855892012-10-17 17:39:35 +02002168/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2169static int
2170smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002171 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002172{
2173 X509 *crt = NULL;
2174 X509_NAME *name;
2175 int ret = 0;
2176 struct chunk *smp_trash;
2177
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002178 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002179 return 0;
2180
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002181 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002182 smp->flags |= SMP_F_MAY_CHANGE;
2183 return 0;
2184 }
2185
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002186 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002187 if (!crt)
2188 goto out;
2189
2190 name = X509_get_issuer_name(crt);
2191 if (!name)
2192 goto out;
2193
Willy Tarreau47ca5452012-12-23 20:22:19 +01002194 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002195 if (args && args[0].type == ARGT_STR) {
2196 int pos = 1;
2197
2198 if (args[1].type == ARGT_SINT)
2199 pos = args[1].data.sint;
2200 else if (args[1].type == ARGT_UINT)
2201 pos =(int)args[1].data.uint;
2202
2203 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2204 goto out;
2205 }
2206 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2207 goto out;
2208
2209 smp->type = SMP_T_STR;
2210 smp->data.str = *smp_trash;
2211 ret = 1;
2212out:
2213 return ret;
2214}
2215
2216/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2217static int
2218smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002219 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002220{
2221 X509 *crt = NULL;
2222 X509_NAME *name;
2223 int ret = 0;
2224 struct chunk *smp_trash;
2225
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002226 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002227 return 0;
2228
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002229 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002230 smp->flags |= SMP_F_MAY_CHANGE;
2231 return 0;
2232 }
2233
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002234 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002235 if (!crt)
2236 goto out;
2237
2238 name = X509_get_subject_name(crt);
2239 if (!name)
2240 goto out;
2241
Willy Tarreau47ca5452012-12-23 20:22:19 +01002242 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002243 if (args && args[0].type == ARGT_STR) {
2244 int pos = 1;
2245
2246 if (args[1].type == ARGT_SINT)
2247 pos = args[1].data.sint;
2248 else if (args[1].type == ARGT_UINT)
2249 pos =(int)args[1].data.uint;
2250
2251 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2252 goto out;
2253 }
2254 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2255 goto out;
2256
2257 smp->type = SMP_T_STR;
2258 smp->data.str = *smp_trash;
2259 ret = 1;
2260out:
2261 return ret;
2262}
2263
Emeric Brun589fcad2012-10-16 14:13:26 +02002264static int
2265smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002266 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002267{
2268 smp->flags = 0;
2269
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002270 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002271 return 0;
2272
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002273 smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002274 if (!smp->data.str.str)
2275 return 0;
2276
2277 smp->type = SMP_T_CSTR;
2278 smp->data.str.len = strlen(smp->data.str.str);
2279
2280 return 1;
2281}
2282
2283static int
2284smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002285 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002286{
2287 smp->flags = 0;
2288
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002289 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002290 return 0;
2291
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002292 if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
Emeric Brun589fcad2012-10-16 14:13:26 +02002293 return 0;
2294
2295 smp->type = SMP_T_UINT;
2296
2297 return 1;
2298}
2299
2300static int
2301smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002302 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002303{
2304 smp->flags = 0;
2305
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002306 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002307 return 0;
2308
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002309 smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002310 if (!smp->data.uint)
2311 return 0;
2312
2313 smp->type = SMP_T_UINT;
2314
2315 return 1;
2316}
2317
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002318#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002319static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002320smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002321 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002322{
Willy Tarreaua33c6542012-10-15 13:19:06 +02002323 smp->flags = 0;
2324 smp->type = SMP_T_CSTR;
2325
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002326 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002327 return 0;
2328
2329 smp->data.str.str = NULL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002330 SSL_get0_next_proto_negotiated(l4->si[0].conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002331 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2332
2333 if (!smp->data.str.str)
2334 return 0;
2335
2336 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002337}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002338#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002339
Willy Tarreauab861d32013-04-02 02:30:41 +02002340#ifdef OPENSSL_ALPN_NEGOTIATED
2341static int
2342smp_fetch_ssl_fc_alpn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002343 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreauab861d32013-04-02 02:30:41 +02002344{
2345 smp->flags = 0;
2346 smp->type = SMP_T_CSTR;
2347
2348 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
2349 return 0;
2350
2351 smp->data.str.str = NULL;
2352 SSL_get0_alpn_negotiated(l4->si[0].conn->xprt_ctx,
2353 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2354
2355 if (!smp->data.str.str)
2356 return 0;
2357
2358 return 1;
2359}
2360#endif
2361
Willy Tarreaua33c6542012-10-15 13:19:06 +02002362static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002363smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002364 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002365{
2366 smp->flags = 0;
2367
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002368 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002369 return 0;
2370
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002371 smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002372 if (!smp->data.str.str)
2373 return 0;
2374
2375 smp->type = SMP_T_CSTR;
2376 smp->data.str.len = strlen(smp->data.str.str);
2377
2378 return 1;
2379}
2380
2381static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002382smp_fetch_ssl_fc_session_id(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 Brunfe68f682012-10-16 14:59:28 +02002384{
2385#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2386 SSL_SESSION *sess;
2387
2388 smp->flags = 0;
2389 smp->type = SMP_T_CBIN;
2390
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002391 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunfe68f682012-10-16 14:59:28 +02002392 return 0;
2393
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002394 sess = SSL_get_session(l4->si[0].conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002395 if (!sess)
2396 return 0;
2397
2398 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2399 if (!smp->data.str.str || !&smp->data.str.len)
2400 return 0;
2401
2402 return 1;
2403#else
2404 return 0;
2405#endif
2406}
2407
2408static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002409smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002410 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002411{
2412#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2413 smp->flags = 0;
2414 smp->type = SMP_T_CSTR;
2415
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002416 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau7875d092012-09-10 08:20:03 +02002417 return 0;
2418
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002419 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 +02002420 if (!smp->data.str.str)
2421 return 0;
2422
Willy Tarreau7875d092012-09-10 08:20:03 +02002423 smp->data.str.len = strlen(smp->data.str.str);
2424 return 1;
2425#else
2426 return 0;
2427#endif
2428}
2429
Emeric Brun2525b6b2012-10-18 15:59:43 +02002430/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002431static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002432smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002433 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002434{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002435 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002436 return 0;
2437
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002438 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002439 smp->flags = SMP_F_MAY_CHANGE;
2440 return 0;
2441 }
2442
2443 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002444 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002445 smp->flags = 0;
2446
2447 return 1;
2448}
2449
Emeric Brun2525b6b2012-10-18 15:59:43 +02002450/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002451static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002452smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002453 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002454{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002455 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002456 return 0;
2457
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002458 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002459 smp->flags = SMP_F_MAY_CHANGE;
2460 return 0;
2461 }
2462
2463 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002464 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002465 smp->flags = 0;
2466
2467 return 1;
2468}
2469
Emeric Brun2525b6b2012-10-18 15:59:43 +02002470/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002471static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002472smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002473 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002474{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002475 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002476 return 0;
2477
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002478 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002479 smp->flags = SMP_F_MAY_CHANGE;
2480 return 0;
2481 }
2482
2483 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002484 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002485 smp->flags = 0;
2486
2487 return 1;
2488}
2489
Emeric Brun2525b6b2012-10-18 15:59:43 +02002490/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002491static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002492smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002493 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002494{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002495 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002496 return 0;
2497
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002498 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002499 smp->flags = SMP_F_MAY_CHANGE;
2500 return 0;
2501 }
2502
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002503 if (!l4->si[0].conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002504 return 0;
2505
2506 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002507 smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002508 smp->flags = 0;
2509
2510 return 1;
2511}
2512
Emeric Brunfb510ea2012-10-05 12:00:26 +02002513/* parse the "ca-file" bind keyword */
2514static 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 +02002515{
2516 if (!*args[cur_arg + 1]) {
2517 if (err)
2518 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2519 return ERR_ALERT | ERR_FATAL;
2520 }
2521
Emeric Brunef42d922012-10-11 16:11:36 +02002522 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2523 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2524 else
2525 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002526
Emeric Brund94b3fe2012-09-20 18:23:56 +02002527 return 0;
2528}
2529
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002530/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002531static 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 +02002532{
2533 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002534 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002535 return ERR_ALERT | ERR_FATAL;
2536 }
2537
Emeric Brun76d88952012-10-05 15:47:31 +02002538 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002539 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002540 return 0;
2541}
2542
2543/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002544static 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 +02002545{
Emeric Brunc8e8d122012-10-02 18:42:10 +02002546 char path[PATH_MAX];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002547 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002548 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002549 return ERR_ALERT | ERR_FATAL;
2550 }
2551
Emeric Brunc8e8d122012-10-02 18:42:10 +02002552 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
2553 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > PATH_MAX) {
2554 memprintf(err, "'%s' : path too long", args[cur_arg]);
2555 return ERR_ALERT | ERR_FATAL;
2556 }
2557 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2558 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2559 return ERR_ALERT | ERR_FATAL;
2560
2561 return 0;
2562 }
2563
Willy Tarreau4348fad2012-09-20 16:48:07 +02002564 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002565 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002566
2567 return 0;
2568}
2569
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002570/* parse the "crt-list" bind keyword */
2571static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2572{
2573 if (!*args[cur_arg + 1]) {
2574 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
2575 return ERR_ALERT | ERR_FATAL;
2576 }
2577
Willy Tarreauad1731d2013-04-02 17:35:58 +02002578 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
2579 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002580 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02002581 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002582
2583 return 0;
2584}
2585
Emeric Brunfb510ea2012-10-05 12:00:26 +02002586/* parse the "crl-file" bind keyword */
2587static 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 +02002588{
Emeric Brun051cdab2012-10-02 19:25:50 +02002589#ifndef X509_V_FLAG_CRL_CHECK
2590 if (err)
2591 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2592 return ERR_ALERT | ERR_FATAL;
2593#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002594 if (!*args[cur_arg + 1]) {
2595 if (err)
2596 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2597 return ERR_ALERT | ERR_FATAL;
2598 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002599
Emeric Brunef42d922012-10-11 16:11:36 +02002600 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2601 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2602 else
2603 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002604
Emeric Brun2b58d042012-09-20 17:10:03 +02002605 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002606#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002607}
2608
2609/* parse the "ecdhe" bind keyword keywords */
2610static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2611{
2612#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2613 if (err)
2614 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2615 return ERR_ALERT | ERR_FATAL;
2616#elif defined(OPENSSL_NO_ECDH)
2617 if (err)
2618 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2619 return ERR_ALERT | ERR_FATAL;
2620#else
2621 if (!*args[cur_arg + 1]) {
2622 if (err)
2623 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2624 return ERR_ALERT | ERR_FATAL;
2625 }
2626
2627 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002628
2629 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002630#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002631}
2632
Emeric Brun81c00f02012-09-21 14:31:21 +02002633/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2634static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2635{
2636 int code;
2637 char *p = args[cur_arg + 1];
2638 unsigned long long *ignerr = &conf->crt_ignerr;
2639
2640 if (!*p) {
2641 if (err)
2642 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2643 return ERR_ALERT | ERR_FATAL;
2644 }
2645
2646 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2647 ignerr = &conf->ca_ignerr;
2648
2649 if (strcmp(p, "all") == 0) {
2650 *ignerr = ~0ULL;
2651 return 0;
2652 }
2653
2654 while (p) {
2655 code = atoi(p);
2656 if ((code <= 0) || (code > 63)) {
2657 if (err)
2658 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2659 args[cur_arg], code, args[cur_arg + 1]);
2660 return ERR_ALERT | ERR_FATAL;
2661 }
2662 *ignerr |= 1ULL << code;
2663 p = strchr(p, ',');
2664 if (p)
2665 p++;
2666 }
2667
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002668 return 0;
2669}
2670
2671/* parse the "force-sslv3" bind keyword */
2672static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2673{
2674 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2675 return 0;
2676}
2677
2678/* parse the "force-tlsv10" bind keyword */
2679static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2680{
2681 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002682 return 0;
2683}
2684
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002685/* parse the "force-tlsv11" bind keyword */
2686static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2687{
2688#if SSL_OP_NO_TLSv1_1
2689 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
2690 return 0;
2691#else
2692 if (err)
2693 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
2694 return ERR_ALERT | ERR_FATAL;
2695#endif
2696}
2697
2698/* parse the "force-tlsv12" bind keyword */
2699static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2700{
2701#if SSL_OP_NO_TLSv1_2
2702 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
2703 return 0;
2704#else
2705 if (err)
2706 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
2707 return ERR_ALERT | ERR_FATAL;
2708#endif
2709}
2710
2711
Emeric Brun2d0c4822012-10-02 13:45:20 +02002712/* parse the "no-tls-tickets" bind keyword */
2713static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2714{
Emeric Brun89675492012-10-05 13:48:26 +02002715 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02002716 return 0;
2717}
2718
Emeric Brun2d0c4822012-10-02 13:45:20 +02002719
Emeric Brun9b3009b2012-10-05 11:55:06 +02002720/* parse the "no-sslv3" bind keyword */
2721static 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 +02002722{
Emeric Brun89675492012-10-05 13:48:26 +02002723 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002724 return 0;
2725}
2726
Emeric Brun9b3009b2012-10-05 11:55:06 +02002727/* parse the "no-tlsv10" bind keyword */
2728static 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 +02002729{
Emeric Brun89675492012-10-05 13:48:26 +02002730 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002731 return 0;
2732}
2733
Emeric Brun9b3009b2012-10-05 11:55:06 +02002734/* parse the "no-tlsv11" bind keyword */
2735static 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 +02002736{
Emeric Brun89675492012-10-05 13:48:26 +02002737 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002738 return 0;
2739}
2740
Emeric Brun9b3009b2012-10-05 11:55:06 +02002741/* parse the "no-tlsv12" bind keyword */
2742static 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 +02002743{
Emeric Brun89675492012-10-05 13:48:26 +02002744 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002745 return 0;
2746}
2747
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002748/* parse the "npn" bind keyword */
2749static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2750{
2751#ifdef OPENSSL_NPN_NEGOTIATED
2752 char *p1, *p2;
2753
2754 if (!*args[cur_arg + 1]) {
2755 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
2756 return ERR_ALERT | ERR_FATAL;
2757 }
2758
2759 free(conf->npn_str);
2760
2761 /* the NPN string is built as a suite of (<len> <name>)* */
2762 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
2763 conf->npn_str = calloc(1, conf->npn_len);
2764 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
2765
2766 /* replace commas with the name length */
2767 p1 = conf->npn_str;
2768 p2 = p1 + 1;
2769 while (1) {
2770 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
2771 if (!p2)
2772 p2 = p1 + 1 + strlen(p1 + 1);
2773
2774 if (p2 - (p1 + 1) > 255) {
2775 *p2 = '\0';
2776 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2777 return ERR_ALERT | ERR_FATAL;
2778 }
2779
2780 *p1 = p2 - (p1 + 1);
2781 p1 = p2;
2782
2783 if (!*p2)
2784 break;
2785
2786 *(p2++) = '\0';
2787 }
2788 return 0;
2789#else
2790 if (err)
2791 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
2792 return ERR_ALERT | ERR_FATAL;
2793#endif
2794}
2795
Willy Tarreauab861d32013-04-02 02:30:41 +02002796/* parse the "alpn" bind keyword */
2797static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2798{
2799#ifdef OPENSSL_ALPN_NEGOTIATED
2800 char *p1, *p2;
2801
2802 if (!*args[cur_arg + 1]) {
2803 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
2804 return ERR_ALERT | ERR_FATAL;
2805 }
2806
2807 free(conf->alpn_str);
2808
2809 /* the ALPN string is built as a suite of (<len> <name>)* */
2810 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
2811 conf->alpn_str = calloc(1, conf->alpn_len);
2812 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
2813
2814 /* replace commas with the name length */
2815 p1 = conf->alpn_str;
2816 p2 = p1 + 1;
2817 while (1) {
2818 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
2819 if (!p2)
2820 p2 = p1 + 1 + strlen(p1 + 1);
2821
2822 if (p2 - (p1 + 1) > 255) {
2823 *p2 = '\0';
2824 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2825 return ERR_ALERT | ERR_FATAL;
2826 }
2827
2828 *p1 = p2 - (p1 + 1);
2829 p1 = p2;
2830
2831 if (!*p2)
2832 break;
2833
2834 *(p2++) = '\0';
2835 }
2836 return 0;
2837#else
2838 if (err)
2839 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
2840 return ERR_ALERT | ERR_FATAL;
2841#endif
2842}
2843
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002844/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002845static 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 +02002846{
Willy Tarreau81796be2012-09-22 19:11:47 +02002847 struct listener *l;
2848
Willy Tarreau4348fad2012-09-20 16:48:07 +02002849 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02002850
2851 if (global.listen_default_ciphers && !conf->ciphers)
2852 conf->ciphers = strdup(global.listen_default_ciphers);
2853
Willy Tarreau81796be2012-09-22 19:11:47 +02002854 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002855 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02002856
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002857 return 0;
2858}
2859
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002860/* parse the "strict-sni" bind keyword */
2861static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2862{
2863 conf->strict_sni = 1;
2864 return 0;
2865}
2866
Emeric Brund94b3fe2012-09-20 18:23:56 +02002867/* parse the "verify" bind keyword */
2868static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2869{
2870 if (!*args[cur_arg + 1]) {
2871 if (err)
2872 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
2873 return ERR_ALERT | ERR_FATAL;
2874 }
2875
2876 if (strcmp(args[cur_arg + 1], "none") == 0)
2877 conf->verify = SSL_VERIFY_NONE;
2878 else if (strcmp(args[cur_arg + 1], "optional") == 0)
2879 conf->verify = SSL_VERIFY_PEER;
2880 else if (strcmp(args[cur_arg + 1], "required") == 0)
2881 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2882 else {
2883 if (err)
2884 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
2885 args[cur_arg], args[cur_arg + 1]);
2886 return ERR_ALERT | ERR_FATAL;
2887 }
2888
2889 return 0;
2890}
2891
Willy Tarreau92faadf2012-10-10 23:04:25 +02002892/************** "server" keywords ****************/
2893
Emeric Brunef42d922012-10-11 16:11:36 +02002894/* parse the "ca-file" server keyword */
2895static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2896{
2897 if (!*args[*cur_arg + 1]) {
2898 if (err)
2899 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
2900 return ERR_ALERT | ERR_FATAL;
2901 }
2902
2903 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2904 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2905 else
2906 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
2907
2908 return 0;
2909}
2910
Willy Tarreau92faadf2012-10-10 23:04:25 +02002911/* parse the "check-ssl" server keyword */
2912static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2913{
2914 newsrv->check.use_ssl = 1;
2915 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2916 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2917 return 0;
2918}
2919
2920/* parse the "ciphers" server keyword */
2921static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2922{
2923 if (!*args[*cur_arg + 1]) {
2924 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
2925 return ERR_ALERT | ERR_FATAL;
2926 }
2927
2928 free(newsrv->ssl_ctx.ciphers);
2929 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
2930 return 0;
2931}
2932
Emeric Brunef42d922012-10-11 16:11:36 +02002933/* parse the "crl-file" server keyword */
2934static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2935{
2936#ifndef X509_V_FLAG_CRL_CHECK
2937 if (err)
2938 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
2939 return ERR_ALERT | ERR_FATAL;
2940#else
2941 if (!*args[*cur_arg + 1]) {
2942 if (err)
2943 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
2944 return ERR_ALERT | ERR_FATAL;
2945 }
2946
2947 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2948 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2949 else
2950 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
2951
2952 return 0;
2953#endif
2954}
2955
Emeric Bruna7aa3092012-10-26 12:58:00 +02002956/* parse the "crt" server keyword */
2957static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2958{
2959 if (!*args[*cur_arg + 1]) {
2960 if (err)
2961 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
2962 return ERR_ALERT | ERR_FATAL;
2963 }
2964
2965 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
2966 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2967 else
2968 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
2969
2970 return 0;
2971}
Emeric Brunef42d922012-10-11 16:11:36 +02002972
Willy Tarreau92faadf2012-10-10 23:04:25 +02002973/* parse the "force-sslv3" server keyword */
2974static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2975{
2976 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
2977 return 0;
2978}
2979
2980/* parse the "force-tlsv10" server keyword */
2981static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2982{
2983 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
2984 return 0;
2985}
2986
2987/* parse the "force-tlsv11" server keyword */
2988static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2989{
2990#if SSL_OP_NO_TLSv1_1
2991 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
2992 return 0;
2993#else
2994 if (err)
2995 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
2996 return ERR_ALERT | ERR_FATAL;
2997#endif
2998}
2999
3000/* parse the "force-tlsv12" server keyword */
3001static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3002{
3003#if SSL_OP_NO_TLSv1_2
3004 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
3005 return 0;
3006#else
3007 if (err)
3008 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
3009 return ERR_ALERT | ERR_FATAL;
3010#endif
3011}
3012
3013/* parse the "no-sslv3" server keyword */
3014static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3015{
3016 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
3017 return 0;
3018}
3019
3020/* parse the "no-tlsv10" server keyword */
3021static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3022{
3023 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
3024 return 0;
3025}
3026
3027/* parse the "no-tlsv11" server keyword */
3028static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3029{
3030 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
3031 return 0;
3032}
3033
3034/* parse the "no-tlsv12" server keyword */
3035static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3036{
3037 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
3038 return 0;
3039}
3040
Emeric Brunf9c5c472012-10-11 15:28:34 +02003041/* parse the "no-tls-tickets" server keyword */
3042static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3043{
3044 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
3045 return 0;
3046}
3047
Willy Tarreau92faadf2012-10-10 23:04:25 +02003048/* parse the "ssl" server keyword */
3049static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3050{
3051 newsrv->use_ssl = 1;
3052 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3053 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3054 return 0;
3055}
3056
Emeric Brunef42d922012-10-11 16:11:36 +02003057/* parse the "verify" server keyword */
3058static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3059{
3060 if (!*args[*cur_arg + 1]) {
3061 if (err)
3062 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
3063 return ERR_ALERT | ERR_FATAL;
3064 }
3065
3066 if (strcmp(args[*cur_arg + 1], "none") == 0)
3067 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
3068 else if (strcmp(args[*cur_arg + 1], "required") == 0)
3069 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
3070 else {
3071 if (err)
3072 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
3073 args[*cur_arg], args[*cur_arg + 1]);
3074 return ERR_ALERT | ERR_FATAL;
3075 }
3076
3077 return 0;
3078}
3079
Willy Tarreau7875d092012-09-10 08:20:03 +02003080/* Note: must not be declared <const> as its list will be overwritten.
3081 * Please take care of keeping this list alphabetically sorted.
3082 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003083static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Willy Tarreau80aca902013-01-07 15:42:20 +01003084 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3085 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3086 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3087 { "ssl_c_i_dn", smp_fetch_ssl_c_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3088 { "ssl_c_key_alg", smp_fetch_ssl_c_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3089 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3090 { "ssl_c_notbefore", smp_fetch_ssl_c_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3091 { "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3092 { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3093 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
James Votha051b4a2013-05-14 20:37:59 +02003094 { "ssl_c_sha1", smp_fetch_ssl_c_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01003095 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3096 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3097 { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3098 { "ssl_f_i_dn", smp_fetch_ssl_f_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3099 { "ssl_f_key_alg", smp_fetch_ssl_f_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3100 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3101 { "ssl_f_notbefore", smp_fetch_ssl_f_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3102 { "ssl_f_sig_alg", smp_fetch_ssl_f_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3103 { "ssl_f_s_dn", smp_fetch_ssl_f_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3104 { "ssl_f_serial", smp_fetch_ssl_f_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3105 { "ssl_f_version", smp_fetch_ssl_f_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3106 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3107 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3108 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3109 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3110 { "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 +02003111#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau80aca902013-01-07 15:42:20 +01003112 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003113#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003114#ifdef OPENSSL_ALPN_NEGOTIATED
3115 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3116#endif
Willy Tarreau80aca902013-01-07 15:42:20 +01003117 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3118 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3119 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_CBIN, SMP_USE_L5CLI },
3120 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreau7875d092012-09-10 08:20:03 +02003121 { NULL, NULL, 0, 0, 0 },
3122}};
3123
3124/* Note: must not be declared <const> as its list will be overwritten.
3125 * Please take care of keeping this list alphabetically sorted.
3126 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003127static struct acl_kw_list acl_kws = {ILH, {
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003128 { "ssl_c_i_dn", NULL, acl_parse_str, acl_match_str },
3129 { "ssl_c_key_alg", NULL, acl_parse_str, acl_match_str },
3130 { "ssl_c_notafter", NULL, acl_parse_str, acl_match_str },
3131 { "ssl_c_notbefore", NULL, acl_parse_str, acl_match_str },
3132 { "ssl_c_sig_alg", NULL, acl_parse_str, acl_match_str },
3133 { "ssl_c_s_dn", NULL, acl_parse_str, acl_match_str },
3134 { "ssl_c_serial", NULL, acl_parse_bin, acl_match_bin },
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003135 { "ssl_f_i_dn", NULL, acl_parse_str, acl_match_str },
3136 { "ssl_f_key_alg", NULL, acl_parse_str, acl_match_str },
3137 { "ssl_f_notafter", NULL, acl_parse_str, acl_match_str },
3138 { "ssl_f_notbefore", NULL, acl_parse_str, acl_match_str },
3139 { "ssl_f_sig_alg", NULL, acl_parse_str, acl_match_str },
3140 { "ssl_f_s_dn", NULL, acl_parse_str, acl_match_str },
3141 { "ssl_f_serial", NULL, acl_parse_bin, acl_match_bin },
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003142 { "ssl_fc_cipher", NULL, acl_parse_str, acl_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003143#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003144 { "ssl_fc_npn", NULL, acl_parse_str, acl_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003145#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003146#ifdef OPENSSL_ALPN_NEGOTIATED
3147 { "ssl_fc_alpn", NULL, acl_parse_str, acl_match_str },
3148#endif
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003149 { "ssl_fc_protocol", NULL, acl_parse_str, acl_match_str },
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003150 { "ssl_fc_sni", "ssl_fc_sni", acl_parse_str, acl_match_str },
3151 { "ssl_fc_sni_end", "ssl_fc_sni", acl_parse_str, acl_match_end },
3152 { "ssl_fc_sni_reg", "ssl_fc_sni", acl_parse_reg, acl_match_reg },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01003153 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02003154}};
3155
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003156/* Note: must not be declared <const> as its list will be overwritten.
3157 * Please take care of keeping this list alphabetically sorted, doing so helps
3158 * all code contributors.
3159 * Optional keywords are also declared with a NULL ->parse() function so that
3160 * the config parser can report an appropriate error when a known keyword was
3161 * not enabled.
3162 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02003163static struct bind_kw_list bind_kws = { "SSL", { }, {
Willy Tarreauab861d32013-04-02 02:30:41 +02003164 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003165 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003166 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
3167 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003168 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003169 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
3170 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003171 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003172 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003173 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
3174 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
3175 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
3176 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02003177 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
3178 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
3179 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
3180 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003181 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003182 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003183 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003184 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003185 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003186 { NULL, NULL, 0 },
3187}};
Emeric Brun46591952012-05-18 15:47:34 +02003188
Willy Tarreau92faadf2012-10-10 23:04:25 +02003189/* Note: must not be declared <const> as its list will be overwritten.
3190 * Please take care of keeping this list alphabetically sorted, doing so helps
3191 * all code contributors.
3192 * Optional keywords are also declared with a NULL ->parse() function so that
3193 * the config parser can report an appropriate error when a known keyword was
3194 * not enabled.
3195 */
3196static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02003197 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003198 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
3199 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02003200 { "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 +02003201 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003202 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
3203 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
3204 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
3205 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
3206 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
3207 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
3208 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
3209 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02003210 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003211 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02003212 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Willy Tarreau92faadf2012-10-10 23:04:25 +02003213 { NULL, NULL, 0, 0 },
3214}};
3215
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003216/* transport-layer operations for SSL sockets */
3217struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02003218 .snd_buf = ssl_sock_from_buf,
3219 .rcv_buf = ssl_sock_to_buf,
3220 .rcv_pipe = NULL,
3221 .snd_pipe = NULL,
3222 .shutr = NULL,
3223 .shutw = ssl_sock_shutw,
3224 .close = ssl_sock_close,
3225 .init = ssl_sock_init,
3226};
3227
3228__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02003229static void __ssl_sock_init(void)
3230{
Emeric Brun46591952012-05-18 15:47:34 +02003231 STACK_OF(SSL_COMP)* cm;
3232
3233 SSL_library_init();
3234 cm = SSL_COMP_get_compression_methods();
3235 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02003236 sample_register_fetches(&sample_fetch_keywords);
3237 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003238 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02003239 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02003240}
3241
3242/*
3243 * Local variables:
3244 * c-indent-level: 8
3245 * c-basic-offset: 8
3246 * End:
3247 */