blob: 8a39dade31d8414bc251e13e63fe4196a3b2e0ec [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 */
1099 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Willy Tarreau20879a02012-12-03 16:32:10 +01001100 if (!conn->err_code)
1101 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01001102 goto out_error;
1103 }
1104 }
1105 /* read some data: consider handshake completed */
1106 goto reneg_ok;
1107 }
1108
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001109 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001110 if (ret != 1) {
1111 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001112 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001113
1114 if (ret == SSL_ERROR_WANT_WRITE) {
1115 /* SSL handshake needs to write, L4 connection may not be ready */
1116 __conn_sock_stop_recv(conn);
1117 __conn_sock_poll_send(conn);
1118 return 0;
1119 }
1120 else if (ret == SSL_ERROR_WANT_READ) {
1121 /* SSL handshake needs to read, L4 connection is ready */
1122 if (conn->flags & CO_FL_WAIT_L4_CONN)
1123 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1124 __conn_sock_stop_send(conn);
1125 __conn_sock_poll_recv(conn);
1126 return 0;
1127 }
Willy Tarreau89230192012-09-28 20:22:13 +02001128 else if (ret == SSL_ERROR_SYSCALL) {
1129 /* if errno is null, then connection was successfully established */
1130 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1131 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001132
1133 if (!((SSL *)conn->xprt_ctx)->packet_length)
1134 if (!errno)
1135 conn->err_code = CO_ER_SSL_EMPTY;
1136 else
1137 conn->err_code = CO_ER_SSL_ABORT;
1138 else
1139 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +02001140 goto out_error;
1141 }
Emeric Brun46591952012-05-18 15:47:34 +02001142 else {
1143 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02001144 /* Note: OpenSSL may leave unread bytes in the socket's
1145 * buffer, causing an RST to be emitted upon close() on
1146 * TCP sockets. We first try to drain possibly pending
1147 * data to avoid this as much as possible.
1148 */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01001149 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Willy Tarreau20879a02012-12-03 16:32:10 +01001150 if (!conn->err_code)
1151 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001152 goto out_error;
1153 }
1154 }
1155
Emeric Brun674b7432012-11-08 19:21:55 +01001156reneg_ok:
1157
Emeric Brun46591952012-05-18 15:47:34 +02001158 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001159 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001160 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +02001161 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001162 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1163 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001164
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001165 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001166 }
1167 }
1168
1169 /* The connection is now established at both layers, it's time to leave */
1170 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1171 return 1;
1172
1173 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001174 /* Clear openssl global errors stack */
1175 ERR_clear_error();
1176
Emeric Brun9fa89732012-10-04 17:09:56 +02001177 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001178 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1179 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1180 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001181 }
1182
Emeric Brun46591952012-05-18 15:47:34 +02001183 /* Fail on all other handshake errors */
1184 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001185 if (!conn->err_code)
1186 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001187 return 0;
1188}
1189
1190/* Receive up to <count> bytes from connection <conn>'s socket and store them
1191 * into buffer <buf>. The caller must ensure that <count> is always smaller
1192 * than the buffer's size. Only one call to recv() is performed, unless the
1193 * buffer wraps, in which case a second call may be performed. The connection's
1194 * flags are updated with whatever special event is detected (error, read0,
1195 * empty). The caller is responsible for taking care of those events and
1196 * avoiding the call if inappropriate. The function does not call the
1197 * connection's polling update function, so the caller is responsible for this.
1198 */
1199static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1200{
1201 int ret, done = 0;
1202 int try = count;
1203
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001204 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001205 goto out_error;
1206
1207 if (conn->flags & CO_FL_HANDSHAKE)
1208 /* a handshake was requested */
1209 return 0;
1210
1211 /* compute the maximum block size we can read at once. */
1212 if (buffer_empty(buf)) {
1213 /* let's realign the buffer to optimize I/O */
1214 buf->p = buf->data;
1215 }
1216 else if (buf->data + buf->o < buf->p &&
1217 buf->p + buf->i < buf->data + buf->size) {
1218 /* remaining space wraps at the end, with a moving limit */
1219 if (try > buf->data + buf->size - (buf->p + buf->i))
1220 try = buf->data + buf->size - (buf->p + buf->i);
1221 }
1222
1223 /* read the largest possible block. For this, we perform only one call
1224 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1225 * in which case we accept to do it once again. A new attempt is made on
1226 * EINTR too.
1227 */
1228 while (try) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001229 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001230 if (conn->flags & CO_FL_ERROR) {
1231 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001232 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001233 }
Emeric Brun46591952012-05-18 15:47:34 +02001234 if (ret > 0) {
1235 buf->i += ret;
1236 done += ret;
1237 if (ret < try)
1238 break;
1239 count -= ret;
1240 try = count;
1241 }
1242 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001243 ret = SSL_get_error(conn->xprt_ctx, ret);
1244 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001245 /* error on protocol or underlying transport */
1246 if ((ret != SSL_ERROR_SYSCALL)
1247 || (errno && (errno != EAGAIN)))
1248 conn->flags |= CO_FL_ERROR;
1249
Emeric Brun644cde02012-12-14 11:21:13 +01001250 /* Clear openssl global errors stack */
1251 ERR_clear_error();
1252 }
Emeric Brun46591952012-05-18 15:47:34 +02001253 goto read0;
1254 }
1255 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001256 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001257 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001258 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001259 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001260 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001261 break;
1262 }
1263 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001264 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1265 /* handshake is running, and it may need to re-enable read */
1266 conn->flags |= CO_FL_SSL_WAIT_HS;
1267 __conn_sock_want_recv(conn);
1268 break;
1269 }
Emeric Brun46591952012-05-18 15:47:34 +02001270 /* we need to poll for retry a read later */
1271 __conn_data_poll_recv(conn);
1272 break;
1273 }
1274 /* otherwise it's a real error */
1275 goto out_error;
1276 }
1277 }
1278 return done;
1279
1280 read0:
1281 conn_sock_read0(conn);
1282 return done;
1283 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001284 /* Clear openssl global errors stack */
1285 ERR_clear_error();
1286
Emeric Brun46591952012-05-18 15:47:34 +02001287 conn->flags |= CO_FL_ERROR;
1288 return done;
1289}
1290
1291
1292/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1293 * <flags> may contain MSG_MORE to make the system hold on without sending
1294 * data too fast, but this flag is ignored at the moment.
1295 * Only one call to send() is performed, unless the buffer wraps, in which case
1296 * a second call may be performed. The connection's flags are updated with
1297 * whatever special event is detected (error, empty). The caller is responsible
1298 * for taking care of those events and avoiding the call if inappropriate. The
1299 * function does not call the connection's polling update function, so the caller
1300 * is responsible for this.
1301 */
1302static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1303{
1304 int ret, try, done;
1305
1306 done = 0;
1307
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001308 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001309 goto out_error;
1310
1311 if (conn->flags & CO_FL_HANDSHAKE)
1312 /* a handshake was requested */
1313 return 0;
1314
1315 /* send the largest possible block. For this we perform only one call
1316 * to send() unless the buffer wraps and we exactly fill the first hunk,
1317 * in which case we accept to do it once again.
1318 */
1319 while (buf->o) {
Kevin Hestercad82342013-05-30 15:12:41 -07001320 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01001321
1322 if (global.tune.ssl_max_record && try > global.tune.ssl_max_record)
1323 try = global.tune.ssl_max_record;
1324
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001325 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001326 if (conn->flags & CO_FL_ERROR) {
1327 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001328 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001329 }
Emeric Brun46591952012-05-18 15:47:34 +02001330 if (ret > 0) {
1331 buf->o -= ret;
1332 done += ret;
1333
Willy Tarreau5fb38032012-12-16 19:39:09 +01001334 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001335 /* optimize data alignment in the buffer */
1336 buf->p = buf->data;
1337
1338 /* if the system buffer is full, don't insist */
1339 if (ret < try)
1340 break;
1341 }
1342 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001343 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001344 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001345 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1346 /* handshake is running, and it may need to re-enable write */
1347 conn->flags |= CO_FL_SSL_WAIT_HS;
1348 __conn_sock_want_send(conn);
1349 break;
1350 }
Emeric Brun46591952012-05-18 15:47:34 +02001351 /* we need to poll to retry a write later */
1352 __conn_data_poll_send(conn);
1353 break;
1354 }
1355 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001356 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001357 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001358 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001359 break;
1360 }
1361 goto out_error;
1362 }
1363 }
1364 return done;
1365
1366 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001367 /* Clear openssl global errors stack */
1368 ERR_clear_error();
1369
Emeric Brun46591952012-05-18 15:47:34 +02001370 conn->flags |= CO_FL_ERROR;
1371 return done;
1372}
1373
Emeric Brun46591952012-05-18 15:47:34 +02001374static void ssl_sock_close(struct connection *conn) {
1375
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001376 if (conn->xprt_ctx) {
1377 SSL_free(conn->xprt_ctx);
1378 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001379 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001380 }
Emeric Brun46591952012-05-18 15:47:34 +02001381}
1382
1383/* This function tries to perform a clean shutdown on an SSL connection, and in
1384 * any case, flags the connection as reusable if no handshake was in progress.
1385 */
1386static void ssl_sock_shutw(struct connection *conn, int clean)
1387{
1388 if (conn->flags & CO_FL_HANDSHAKE)
1389 return;
1390 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001391 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1392 /* Clear openssl global errors stack */
1393 ERR_clear_error();
1394 }
Emeric Brun46591952012-05-18 15:47:34 +02001395
1396 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001397 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001398}
1399
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001400/* used for logging, may be changed for a sample fetch later */
1401const char *ssl_sock_get_cipher_name(struct connection *conn)
1402{
1403 if (!conn->xprt && !conn->xprt_ctx)
1404 return NULL;
1405 return SSL_get_cipher_name(conn->xprt_ctx);
1406}
1407
1408/* used for logging, may be changed for a sample fetch later */
1409const char *ssl_sock_get_proto_version(struct connection *conn)
1410{
1411 if (!conn->xprt && !conn->xprt_ctx)
1412 return NULL;
1413 return SSL_get_version(conn->xprt_ctx);
1414}
1415
Willy Tarreau8d598402012-10-22 17:58:39 +02001416/* Extract a serial from a cert, and copy it to a chunk.
1417 * Returns 1 if serial is found and copied, 0 if no serial found and
1418 * -1 if output is not large enough.
1419 */
1420static int
1421ssl_sock_get_serial(X509 *crt, struct chunk *out)
1422{
1423 ASN1_INTEGER *serial;
1424
1425 serial = X509_get_serialNumber(crt);
1426 if (!serial)
1427 return 0;
1428
1429 if (out->size < serial->length)
1430 return -1;
1431
1432 memcpy(out->str, serial->data, serial->length);
1433 out->len = serial->length;
1434 return 1;
1435}
1436
Emeric Brunce5ad802012-10-22 14:11:22 +02001437
1438/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1439 * Returns 1 if serial is found and copied, 0 if no valid time found
1440 * and -1 if output is not large enough.
1441 */
1442static int
1443ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1444{
1445 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1446 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1447
1448 if (gentm->length < 12)
1449 return 0;
1450 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1451 return 0;
1452 if (out->size < gentm->length-2)
1453 return -1;
1454
1455 memcpy(out->str, gentm->data+2, gentm->length-2);
1456 out->len = gentm->length-2;
1457 return 1;
1458 }
1459 else if (tm->type == V_ASN1_UTCTIME) {
1460 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1461
1462 if (utctm->length < 10)
1463 return 0;
1464 if (utctm->data[0] >= 0x35)
1465 return 0;
1466 if (out->size < utctm->length)
1467 return -1;
1468
1469 memcpy(out->str, utctm->data, utctm->length);
1470 out->len = utctm->length;
1471 return 1;
1472 }
1473
1474 return 0;
1475}
1476
Emeric Brun87855892012-10-17 17:39:35 +02001477/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1478 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1479 */
1480static int
1481ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1482{
1483 X509_NAME_ENTRY *ne;
1484 int i, j, n;
1485 int cur = 0;
1486 const char *s;
1487 char tmp[128];
1488
1489 out->len = 0;
1490 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1491 if (pos < 0)
1492 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1493 else
1494 j = i;
1495
1496 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1497 n = OBJ_obj2nid(ne->object);
1498 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1499 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1500 s = tmp;
1501 }
1502
1503 if (chunk_strcasecmp(entry, s) != 0)
1504 continue;
1505
1506 if (pos < 0)
1507 cur--;
1508 else
1509 cur++;
1510
1511 if (cur != pos)
1512 continue;
1513
1514 if (ne->value->length > out->size)
1515 return -1;
1516
1517 memcpy(out->str, ne->value->data, ne->value->length);
1518 out->len = ne->value->length;
1519 return 1;
1520 }
1521
1522 return 0;
1523
1524}
1525
1526/* Extract and format full DN from a X509_NAME and copy result into a chunk
1527 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1528 */
1529static int
1530ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1531{
1532 X509_NAME_ENTRY *ne;
1533 int i, n, ln;
1534 int l = 0;
1535 const char *s;
1536 char *p;
1537 char tmp[128];
1538
1539 out->len = 0;
1540 p = out->str;
1541 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1542 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1543 n = OBJ_obj2nid(ne->object);
1544 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1545 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1546 s = tmp;
1547 }
1548 ln = strlen(s);
1549
1550 l += 1 + ln + 1 + ne->value->length;
1551 if (l > out->size)
1552 return -1;
1553 out->len = l;
1554
1555 *(p++)='/';
1556 memcpy(p, s, ln);
1557 p += ln;
1558 *(p++)='=';
1559 memcpy(p, ne->value->data, ne->value->length);
1560 p += ne->value->length;
1561 }
1562
1563 if (!out->len)
1564 return 0;
1565
1566 return 1;
1567}
1568
Willy Tarreau7875d092012-09-10 08:20:03 +02001569/***** Below are some sample fetching functions for ACL/patterns *****/
1570
Emeric Brune64aef12012-09-21 13:15:06 +02001571/* boolean, returns true if client cert was present */
1572static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001573smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1574 const struct arg *args, struct sample *smp)
Emeric Brune64aef12012-09-21 13:15:06 +02001575{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001576 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001577 return 0;
1578
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001579 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001580 smp->flags |= SMP_F_MAY_CHANGE;
1581 return 0;
1582 }
1583
1584 smp->flags = 0;
1585 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001586 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001587
1588 return 1;
1589}
1590
Willy Tarreau8d598402012-10-22 17:58:39 +02001591/* bin, returns serial in a binary chunk */
1592static int
1593smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1594 const struct arg *args, struct sample *smp)
1595{
1596 X509 *crt = NULL;
1597 int ret = 0;
1598 struct chunk *smp_trash;
1599
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001600 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001601 return 0;
1602
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001603 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001604 smp->flags |= SMP_F_MAY_CHANGE;
1605 return 0;
1606 }
1607
1608 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001609 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001610 if (!crt)
1611 goto out;
1612
Willy Tarreau47ca5452012-12-23 20:22:19 +01001613 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001614 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1615 goto out;
1616
1617 smp->data.str = *smp_trash;
1618 smp->type = SMP_T_BIN;
1619 ret = 1;
1620out:
1621 if (crt)
1622 X509_free(crt);
1623 return ret;
1624}
Emeric Brune64aef12012-09-21 13:15:06 +02001625
James Votha051b4a2013-05-14 20:37:59 +02001626/* bin, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk */
1627static int
1628smp_fetch_ssl_c_sha1(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1629 const struct arg *args, struct sample *smp)
1630{
1631 X509 *crt = NULL;
1632 const EVP_MD *digest;
1633 int ret = 0;
1634 struct chunk *smp_trash;
1635
1636 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
1637 return 0;
1638
1639 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
1640 smp->flags |= SMP_F_MAY_CHANGE;
1641 return 0;
1642 }
1643
1644 /* SSL_get_peer_certificate, it increase X509 * ref count */
1645 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
1646 if (!crt)
1647 goto out;
1648
1649 smp_trash = get_trash_chunk();
1650 digest = EVP_sha1();
1651 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
1652
1653 smp->data.str = *smp_trash;
1654 smp->type = SMP_T_BIN;
1655 ret = 1;
1656out:
1657 if (crt)
1658 X509_free(crt);
1659 return ret;
1660}
1661
Emeric Brunce5ad802012-10-22 14:11:22 +02001662/*str, returns notafter date in ASN1_UTCTIME format */
1663static int
1664smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1665 const struct arg *args, struct sample *smp)
1666{
1667 X509 *crt = NULL;
1668 int ret = 0;
1669 struct chunk *smp_trash;
1670
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001671 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001672 return 0;
1673
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001674 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001675 smp->flags |= SMP_F_MAY_CHANGE;
1676 return 0;
1677 }
1678
1679 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001680 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001681 if (!crt)
1682 goto out;
1683
Willy Tarreau47ca5452012-12-23 20:22:19 +01001684 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001685 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1686 goto out;
1687
1688 smp->data.str = *smp_trash;
1689 smp->type = SMP_T_STR;
1690 ret = 1;
1691out:
1692 if (crt)
1693 X509_free(crt);
1694 return ret;
1695}
1696
Emeric Brun87855892012-10-17 17:39:35 +02001697/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1698static int
1699smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1700 const struct arg *args, struct sample *smp)
1701{
1702 X509 *crt = NULL;
1703 X509_NAME *name;
1704 int ret = 0;
1705 struct chunk *smp_trash;
1706
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001707 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001708 return 0;
1709
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001710 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001711 smp->flags |= SMP_F_MAY_CHANGE;
1712 return 0;
1713 }
1714
1715 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001716 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001717 if (!crt)
1718 goto out;
1719
1720 name = X509_get_issuer_name(crt);
1721 if (!name)
1722 goto out;
1723
Willy Tarreau47ca5452012-12-23 20:22:19 +01001724 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001725 if (args && args[0].type == ARGT_STR) {
1726 int pos = 1;
1727
1728 if (args[1].type == ARGT_SINT)
1729 pos = args[1].data.sint;
1730 else if (args[1].type == ARGT_UINT)
1731 pos =(int)args[1].data.uint;
1732
1733 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1734 goto out;
1735 }
1736 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1737 goto out;
1738
1739 smp->type = SMP_T_STR;
1740 smp->data.str = *smp_trash;
1741 ret = 1;
1742out:
1743 if (crt)
1744 X509_free(crt);
1745 return ret;
1746}
1747
Emeric Brunce5ad802012-10-22 14:11:22 +02001748/*str, returns notbefore date in ASN1_UTCTIME format */
1749static int
1750smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1751 const struct arg *args, struct sample *smp)
1752{
1753 X509 *crt = NULL;
1754 int ret = 0;
1755 struct chunk *smp_trash;
1756
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001757 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001758 return 0;
1759
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001760 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001761 smp->flags |= SMP_F_MAY_CHANGE;
1762 return 0;
1763 }
1764
1765 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001766 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001767 if (!crt)
1768 goto out;
1769
Willy Tarreau47ca5452012-12-23 20:22:19 +01001770 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001771 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1772 goto out;
1773
1774 smp->data.str = *smp_trash;
1775 smp->type = SMP_T_STR;
1776 ret = 1;
1777out:
1778 if (crt)
1779 X509_free(crt);
1780 return ret;
1781}
1782
Emeric Brun87855892012-10-17 17:39:35 +02001783/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1784static int
1785smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1786 const struct arg *args, struct sample *smp)
1787{
1788 X509 *crt = NULL;
1789 X509_NAME *name;
1790 int ret = 0;
1791 struct chunk *smp_trash;
1792
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001793 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001794 return 0;
1795
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001796 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001797 smp->flags |= SMP_F_MAY_CHANGE;
1798 return 0;
1799 }
1800
1801 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001802 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001803 if (!crt)
1804 goto out;
1805
1806 name = X509_get_subject_name(crt);
1807 if (!name)
1808 goto out;
1809
Willy Tarreau47ca5452012-12-23 20:22:19 +01001810 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001811 if (args && args[0].type == ARGT_STR) {
1812 int pos = 1;
1813
1814 if (args[1].type == ARGT_SINT)
1815 pos = args[1].data.sint;
1816 else if (args[1].type == ARGT_UINT)
1817 pos =(int)args[1].data.uint;
1818
1819 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1820 goto out;
1821 }
1822 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1823 goto out;
1824
1825 smp->type = SMP_T_STR;
1826 smp->data.str = *smp_trash;
1827 ret = 1;
1828out:
1829 if (crt)
1830 X509_free(crt);
1831 return ret;
1832}
Emeric Brun9143d372012-12-20 15:44:16 +01001833
1834/* integer, returns true if current session use a client certificate */
1835static int
1836smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1837 const struct arg *args, struct sample *smp)
1838{
1839 X509 *crt;
1840
1841 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
1842 return 0;
1843
1844 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
1845 smp->flags |= SMP_F_MAY_CHANGE;
1846 return 0;
1847 }
1848
1849 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
1850 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
1851 if (crt) {
1852 X509_free(crt);
1853 }
1854
1855 smp->type = SMP_T_BOOL;
1856 smp->data.uint = (crt != NULL);
1857 return 1;
1858}
1859
Emeric Bruna7359fd2012-10-17 15:03:11 +02001860/* integer, returns the client certificate version */
1861static int
1862smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1863 const struct arg *args, struct sample *smp)
1864{
1865 X509 *crt;
1866
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001867 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001868 return 0;
1869
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001870 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001871 smp->flags |= SMP_F_MAY_CHANGE;
1872 return 0;
1873 }
1874
1875 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001876 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001877 if (!crt)
1878 return 0;
1879
1880 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1881 X509_free(crt);
1882 smp->type = SMP_T_UINT;
1883
1884 return 1;
1885}
1886
Emeric Brun7f56e742012-10-19 18:15:40 +02001887/* str, returns the client certificate sig alg */
1888static int
1889smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1890 const struct arg *args, struct sample *smp)
1891{
1892 X509 *crt;
1893 int nid;
1894
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001895 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02001896 return 0;
1897
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001898 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02001899 smp->flags |= SMP_F_MAY_CHANGE;
1900 return 0;
1901 }
1902
1903 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001904 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02001905 if (!crt)
1906 return 0;
1907
1908 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1909
1910 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1911 if (!smp->data.str.str)
1912 return 0;
1913
1914 smp->type = SMP_T_CSTR;
1915 smp->data.str.len = strlen(smp->data.str.str);
1916 X509_free(crt);
1917
1918 return 1;
1919}
1920
Emeric Brun521a0112012-10-22 12:22:55 +02001921/* str, returns the client certificate key alg */
1922static int
1923smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1924 const struct arg *args, struct sample *smp)
1925{
1926 X509 *crt;
1927 int nid;
1928
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001929 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02001930 return 0;
1931
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001932 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02001933 smp->flags |= SMP_F_MAY_CHANGE;
1934 return 0;
1935 }
1936
1937 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001938 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02001939 if (!crt)
1940 return 0;
1941
1942 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1943
1944 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1945 if (!smp->data.str.str)
1946 return 0;
1947
1948 smp->type = SMP_T_CSTR;
1949 smp->data.str.len = strlen(smp->data.str.str);
1950 X509_free(crt);
1951
1952 return 1;
1953}
1954
Emeric Brun2525b6b2012-10-18 15:59:43 +02001955/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02001956static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001957smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau7875d092012-09-10 08:20:03 +02001958 const struct arg *args, struct sample *smp)
1959{
1960 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001961 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02001962 return 1;
1963}
1964
Emeric Brun2525b6b2012-10-18 15:59:43 +02001965/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02001966static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001967smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1968 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02001969{
1970#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1971 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001972 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock) &&
1973 l4->si[0].conn->xprt_ctx &&
1974 SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02001975 return 1;
1976#else
1977 return 0;
1978#endif
1979}
1980
Willy Tarreau8d598402012-10-22 17:58:39 +02001981/* bin, returns serial in a binary chunk */
1982static int
1983smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1984 const struct arg *args, struct sample *smp)
1985{
1986 X509 *crt = NULL;
1987 int ret = 0;
1988 struct chunk *smp_trash;
1989
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001990 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001991 return 0;
1992
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001993 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001994 smp->flags |= SMP_F_MAY_CHANGE;
1995 return 0;
1996 }
1997
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001998 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001999 if (!crt)
2000 goto out;
2001
Willy Tarreau47ca5452012-12-23 20:22:19 +01002002 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02002003 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
2004 goto out;
2005
2006 smp->data.str = *smp_trash;
2007 smp->type = SMP_T_BIN;
2008 ret = 1;
2009out:
2010 return ret;
2011}
Emeric Brunce5ad802012-10-22 14:11:22 +02002012/*str, returns notafter date in ASN1_UTCTIME format */
2013static int
2014smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2015 const struct arg *args, struct sample *smp)
2016{
2017 X509 *crt = NULL;
2018 int ret = 0;
2019 struct chunk *smp_trash;
2020
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002021 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02002022 return 0;
2023
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002024 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002025 smp->flags |= SMP_F_MAY_CHANGE;
2026 return 0;
2027 }
2028
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002029 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002030 if (!crt)
2031 goto out;
2032
Willy Tarreau47ca5452012-12-23 20:22:19 +01002033 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002034 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
2035 goto out;
2036
2037 smp->data.str = *smp_trash;
2038 smp->type = SMP_T_STR;
2039 ret = 1;
2040out:
2041 return ret;
2042}
2043
2044/*str, returns notbefore date in ASN1_UTCTIME format */
2045static int
2046smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2047 const struct arg *args, struct sample *smp)
2048{
2049 X509 *crt = NULL;
2050 int ret = 0;
2051 struct chunk *smp_trash;
2052
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002053 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02002054 return 0;
2055
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002056 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002057 smp->flags |= SMP_F_MAY_CHANGE;
2058 return 0;
2059 }
2060
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002061 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002062 if (!crt)
2063 goto out;
2064
Willy Tarreau47ca5452012-12-23 20:22:19 +01002065 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002066 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
2067 goto out;
2068
2069 smp->data.str = *smp_trash;
2070 smp->type = SMP_T_STR;
2071 ret = 1;
2072out:
2073 return ret;
2074}
Willy Tarreau8d598402012-10-22 17:58:39 +02002075
Emeric Bruna7359fd2012-10-17 15:03:11 +02002076/* integer, returns the frontend certificate version */
2077static int
2078smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2079 const struct arg *args, struct sample *smp)
2080{
2081 X509 *crt;
2082
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002083 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002084 return 0;
2085
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002086 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002087 smp->flags |= SMP_F_MAY_CHANGE;
2088 return 0;
2089 }
2090
2091 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002092 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002093 if (!crt)
2094 return 0;
2095
2096 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2097 smp->type = SMP_T_UINT;
2098
2099 return 1;
2100}
2101
Emeric Brun7f56e742012-10-19 18:15:40 +02002102/* str, returns the client certificate sig alg */
2103static int
2104smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2105 const struct arg *args, struct sample *smp)
2106{
2107 X509 *crt;
2108 int nid;
2109
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002110 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02002111 return 0;
2112
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002113 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002114 smp->flags |= SMP_F_MAY_CHANGE;
2115 return 0;
2116 }
2117
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002118 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002119 if (!crt)
2120 return 0;
2121
2122 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2123
2124 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2125 if (!smp->data.str.str)
2126 return 0;
2127
2128 smp->type = SMP_T_CSTR;
2129 smp->data.str.len = strlen(smp->data.str.str);
2130
2131 return 1;
2132}
2133
Emeric Brun521a0112012-10-22 12:22:55 +02002134/* str, returns the client certificate key alg */
2135static int
2136smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2137 const struct arg *args, struct sample *smp)
2138{
2139 X509 *crt;
2140 int nid;
2141
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002142 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002143 return 0;
2144
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002145 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002146 smp->flags |= SMP_F_MAY_CHANGE;
2147 return 0;
2148 }
2149
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002150 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002151 if (!crt)
2152 return 0;
2153
2154 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2155
2156 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2157 if (!smp->data.str.str)
2158 return 0;
2159
2160 smp->type = SMP_T_CSTR;
2161 smp->data.str.len = strlen(smp->data.str.str);
2162
2163 return 1;
2164}
2165
Emeric Brun87855892012-10-17 17:39:35 +02002166/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2167static int
2168smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2169 const struct arg *args, struct sample *smp)
2170{
2171 X509 *crt = NULL;
2172 X509_NAME *name;
2173 int ret = 0;
2174 struct chunk *smp_trash;
2175
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002176 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002177 return 0;
2178
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002179 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002180 smp->flags |= SMP_F_MAY_CHANGE;
2181 return 0;
2182 }
2183
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002184 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002185 if (!crt)
2186 goto out;
2187
2188 name = X509_get_issuer_name(crt);
2189 if (!name)
2190 goto out;
2191
Willy Tarreau47ca5452012-12-23 20:22:19 +01002192 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002193 if (args && args[0].type == ARGT_STR) {
2194 int pos = 1;
2195
2196 if (args[1].type == ARGT_SINT)
2197 pos = args[1].data.sint;
2198 else if (args[1].type == ARGT_UINT)
2199 pos =(int)args[1].data.uint;
2200
2201 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2202 goto out;
2203 }
2204 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2205 goto out;
2206
2207 smp->type = SMP_T_STR;
2208 smp->data.str = *smp_trash;
2209 ret = 1;
2210out:
2211 return ret;
2212}
2213
2214/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2215static int
2216smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2217 const struct arg *args, struct sample *smp)
2218{
2219 X509 *crt = NULL;
2220 X509_NAME *name;
2221 int ret = 0;
2222 struct chunk *smp_trash;
2223
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002224 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002225 return 0;
2226
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002227 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002228 smp->flags |= SMP_F_MAY_CHANGE;
2229 return 0;
2230 }
2231
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002232 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002233 if (!crt)
2234 goto out;
2235
2236 name = X509_get_subject_name(crt);
2237 if (!name)
2238 goto out;
2239
Willy Tarreau47ca5452012-12-23 20:22:19 +01002240 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002241 if (args && args[0].type == ARGT_STR) {
2242 int pos = 1;
2243
2244 if (args[1].type == ARGT_SINT)
2245 pos = args[1].data.sint;
2246 else if (args[1].type == ARGT_UINT)
2247 pos =(int)args[1].data.uint;
2248
2249 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2250 goto out;
2251 }
2252 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2253 goto out;
2254
2255 smp->type = SMP_T_STR;
2256 smp->data.str = *smp_trash;
2257 ret = 1;
2258out:
2259 return ret;
2260}
2261
Emeric Brun589fcad2012-10-16 14:13:26 +02002262static int
2263smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2264 const struct arg *args, struct sample *smp)
2265{
2266 smp->flags = 0;
2267
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002268 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002269 return 0;
2270
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002271 smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002272 if (!smp->data.str.str)
2273 return 0;
2274
2275 smp->type = SMP_T_CSTR;
2276 smp->data.str.len = strlen(smp->data.str.str);
2277
2278 return 1;
2279}
2280
2281static int
2282smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2283 const struct arg *args, struct sample *smp)
2284{
2285 smp->flags = 0;
2286
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002287 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002288 return 0;
2289
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002290 if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
Emeric Brun589fcad2012-10-16 14:13:26 +02002291 return 0;
2292
2293 smp->type = SMP_T_UINT;
2294
2295 return 1;
2296}
2297
2298static int
2299smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2300 const struct arg *args, struct sample *smp)
2301{
2302 smp->flags = 0;
2303
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002304 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002305 return 0;
2306
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002307 smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002308 if (!smp->data.uint)
2309 return 0;
2310
2311 smp->type = SMP_T_UINT;
2312
2313 return 1;
2314}
2315
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002316#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002317static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002318smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2319 const struct arg *args, struct sample *smp)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002320{
Willy Tarreaua33c6542012-10-15 13:19:06 +02002321 smp->flags = 0;
2322 smp->type = SMP_T_CSTR;
2323
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002324 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002325 return 0;
2326
2327 smp->data.str.str = NULL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002328 SSL_get0_next_proto_negotiated(l4->si[0].conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002329 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2330
2331 if (!smp->data.str.str)
2332 return 0;
2333
2334 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002335}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002336#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002337
Willy Tarreauab861d32013-04-02 02:30:41 +02002338#ifdef OPENSSL_ALPN_NEGOTIATED
2339static int
2340smp_fetch_ssl_fc_alpn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2341 const struct arg *args, struct sample *smp)
2342{
2343 smp->flags = 0;
2344 smp->type = SMP_T_CSTR;
2345
2346 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
2347 return 0;
2348
2349 smp->data.str.str = NULL;
2350 SSL_get0_alpn_negotiated(l4->si[0].conn->xprt_ctx,
2351 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2352
2353 if (!smp->data.str.str)
2354 return 0;
2355
2356 return 1;
2357}
2358#endif
2359
Willy Tarreaua33c6542012-10-15 13:19:06 +02002360static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002361smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2362 const struct arg *args, struct sample *smp)
2363{
2364 smp->flags = 0;
2365
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002366 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002367 return 0;
2368
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002369 smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002370 if (!smp->data.str.str)
2371 return 0;
2372
2373 smp->type = SMP_T_CSTR;
2374 smp->data.str.len = strlen(smp->data.str.str);
2375
2376 return 1;
2377}
2378
2379static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002380smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2381 const struct arg *args, struct sample *smp)
2382{
2383#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2384 SSL_SESSION *sess;
2385
2386 smp->flags = 0;
2387 smp->type = SMP_T_CBIN;
2388
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002389 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunfe68f682012-10-16 14:59:28 +02002390 return 0;
2391
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002392 sess = SSL_get_session(l4->si[0].conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002393 if (!sess)
2394 return 0;
2395
2396 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2397 if (!smp->data.str.str || !&smp->data.str.len)
2398 return 0;
2399
2400 return 1;
2401#else
2402 return 0;
2403#endif
2404}
2405
2406static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002407smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2408 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02002409{
2410#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2411 smp->flags = 0;
2412 smp->type = SMP_T_CSTR;
2413
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002414 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau7875d092012-09-10 08:20:03 +02002415 return 0;
2416
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002417 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 +02002418 if (!smp->data.str.str)
2419 return 0;
2420
Willy Tarreau7875d092012-09-10 08:20:03 +02002421 smp->data.str.len = strlen(smp->data.str.str);
2422 return 1;
2423#else
2424 return 0;
2425#endif
2426}
2427
Emeric Brun2525b6b2012-10-18 15:59:43 +02002428/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002429static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002430smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002431 const struct arg *args, struct sample *smp)
2432{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002433 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002434 return 0;
2435
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002436 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002437 smp->flags = SMP_F_MAY_CHANGE;
2438 return 0;
2439 }
2440
2441 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002442 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002443 smp->flags = 0;
2444
2445 return 1;
2446}
2447
Emeric Brun2525b6b2012-10-18 15:59:43 +02002448/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002449static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002450smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002451 const struct arg *args, struct sample *smp)
2452{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002453 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002454 return 0;
2455
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002456 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002457 smp->flags = SMP_F_MAY_CHANGE;
2458 return 0;
2459 }
2460
2461 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002462 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002463 smp->flags = 0;
2464
2465 return 1;
2466}
2467
Emeric Brun2525b6b2012-10-18 15:59:43 +02002468/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002469static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002470smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2471 const struct arg *args, struct sample *smp)
Emeric Brunf282a812012-09-21 15:27:54 +02002472{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002473 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002474 return 0;
2475
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002476 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002477 smp->flags = SMP_F_MAY_CHANGE;
2478 return 0;
2479 }
2480
2481 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002482 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002483 smp->flags = 0;
2484
2485 return 1;
2486}
2487
Emeric Brun2525b6b2012-10-18 15:59:43 +02002488/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002489static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002490smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2491 const struct arg *args, struct sample *smp)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002492{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002493 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002494 return 0;
2495
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002496 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002497 smp->flags = SMP_F_MAY_CHANGE;
2498 return 0;
2499 }
2500
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002501 if (!l4->si[0].conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002502 return 0;
2503
2504 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002505 smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002506 smp->flags = 0;
2507
2508 return 1;
2509}
2510
Emeric Brunfb510ea2012-10-05 12:00:26 +02002511/* parse the "ca-file" bind keyword */
2512static 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 +02002513{
2514 if (!*args[cur_arg + 1]) {
2515 if (err)
2516 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2517 return ERR_ALERT | ERR_FATAL;
2518 }
2519
Emeric Brunef42d922012-10-11 16:11:36 +02002520 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2521 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2522 else
2523 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002524
Emeric Brund94b3fe2012-09-20 18:23:56 +02002525 return 0;
2526}
2527
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002528/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002529static 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 +02002530{
2531 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002532 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002533 return ERR_ALERT | ERR_FATAL;
2534 }
2535
Emeric Brun76d88952012-10-05 15:47:31 +02002536 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002537 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002538 return 0;
2539}
2540
2541/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002542static 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 +02002543{
Emeric Brunc8e8d122012-10-02 18:42:10 +02002544 char path[PATH_MAX];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002545 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002546 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002547 return ERR_ALERT | ERR_FATAL;
2548 }
2549
Emeric Brunc8e8d122012-10-02 18:42:10 +02002550 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
2551 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > PATH_MAX) {
2552 memprintf(err, "'%s' : path too long", args[cur_arg]);
2553 return ERR_ALERT | ERR_FATAL;
2554 }
2555 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2556 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2557 return ERR_ALERT | ERR_FATAL;
2558
2559 return 0;
2560 }
2561
Willy Tarreau4348fad2012-09-20 16:48:07 +02002562 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002563 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002564
2565 return 0;
2566}
2567
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002568/* parse the "crt-list" bind keyword */
2569static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2570{
2571 if (!*args[cur_arg + 1]) {
2572 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
2573 return ERR_ALERT | ERR_FATAL;
2574 }
2575
Willy Tarreauad1731d2013-04-02 17:35:58 +02002576 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
2577 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002578 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02002579 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002580
2581 return 0;
2582}
2583
Emeric Brunfb510ea2012-10-05 12:00:26 +02002584/* parse the "crl-file" bind keyword */
2585static 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 +02002586{
Emeric Brun051cdab2012-10-02 19:25:50 +02002587#ifndef X509_V_FLAG_CRL_CHECK
2588 if (err)
2589 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2590 return ERR_ALERT | ERR_FATAL;
2591#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002592 if (!*args[cur_arg + 1]) {
2593 if (err)
2594 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2595 return ERR_ALERT | ERR_FATAL;
2596 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002597
Emeric Brunef42d922012-10-11 16:11:36 +02002598 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2599 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2600 else
2601 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002602
Emeric Brun2b58d042012-09-20 17:10:03 +02002603 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002604#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002605}
2606
2607/* parse the "ecdhe" bind keyword keywords */
2608static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2609{
2610#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2611 if (err)
2612 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2613 return ERR_ALERT | ERR_FATAL;
2614#elif defined(OPENSSL_NO_ECDH)
2615 if (err)
2616 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2617 return ERR_ALERT | ERR_FATAL;
2618#else
2619 if (!*args[cur_arg + 1]) {
2620 if (err)
2621 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2622 return ERR_ALERT | ERR_FATAL;
2623 }
2624
2625 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002626
2627 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002628#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002629}
2630
Emeric Brun81c00f02012-09-21 14:31:21 +02002631/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2632static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2633{
2634 int code;
2635 char *p = args[cur_arg + 1];
2636 unsigned long long *ignerr = &conf->crt_ignerr;
2637
2638 if (!*p) {
2639 if (err)
2640 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2641 return ERR_ALERT | ERR_FATAL;
2642 }
2643
2644 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2645 ignerr = &conf->ca_ignerr;
2646
2647 if (strcmp(p, "all") == 0) {
2648 *ignerr = ~0ULL;
2649 return 0;
2650 }
2651
2652 while (p) {
2653 code = atoi(p);
2654 if ((code <= 0) || (code > 63)) {
2655 if (err)
2656 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2657 args[cur_arg], code, args[cur_arg + 1]);
2658 return ERR_ALERT | ERR_FATAL;
2659 }
2660 *ignerr |= 1ULL << code;
2661 p = strchr(p, ',');
2662 if (p)
2663 p++;
2664 }
2665
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002666 return 0;
2667}
2668
2669/* parse the "force-sslv3" bind keyword */
2670static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2671{
2672 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2673 return 0;
2674}
2675
2676/* parse the "force-tlsv10" bind keyword */
2677static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2678{
2679 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002680 return 0;
2681}
2682
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002683/* parse the "force-tlsv11" bind keyword */
2684static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2685{
2686#if SSL_OP_NO_TLSv1_1
2687 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
2688 return 0;
2689#else
2690 if (err)
2691 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
2692 return ERR_ALERT | ERR_FATAL;
2693#endif
2694}
2695
2696/* parse the "force-tlsv12" bind keyword */
2697static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2698{
2699#if SSL_OP_NO_TLSv1_2
2700 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
2701 return 0;
2702#else
2703 if (err)
2704 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
2705 return ERR_ALERT | ERR_FATAL;
2706#endif
2707}
2708
2709
Emeric Brun2d0c4822012-10-02 13:45:20 +02002710/* parse the "no-tls-tickets" bind keyword */
2711static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2712{
Emeric Brun89675492012-10-05 13:48:26 +02002713 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02002714 return 0;
2715}
2716
Emeric Brun2d0c4822012-10-02 13:45:20 +02002717
Emeric Brun9b3009b2012-10-05 11:55:06 +02002718/* parse the "no-sslv3" bind keyword */
2719static 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 +02002720{
Emeric Brun89675492012-10-05 13:48:26 +02002721 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002722 return 0;
2723}
2724
Emeric Brun9b3009b2012-10-05 11:55:06 +02002725/* parse the "no-tlsv10" bind keyword */
2726static 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 +02002727{
Emeric Brun89675492012-10-05 13:48:26 +02002728 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002729 return 0;
2730}
2731
Emeric Brun9b3009b2012-10-05 11:55:06 +02002732/* parse the "no-tlsv11" bind keyword */
2733static 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 +02002734{
Emeric Brun89675492012-10-05 13:48:26 +02002735 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002736 return 0;
2737}
2738
Emeric Brun9b3009b2012-10-05 11:55:06 +02002739/* parse the "no-tlsv12" bind keyword */
2740static 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 +02002741{
Emeric Brun89675492012-10-05 13:48:26 +02002742 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002743 return 0;
2744}
2745
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002746/* parse the "npn" bind keyword */
2747static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2748{
2749#ifdef OPENSSL_NPN_NEGOTIATED
2750 char *p1, *p2;
2751
2752 if (!*args[cur_arg + 1]) {
2753 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
2754 return ERR_ALERT | ERR_FATAL;
2755 }
2756
2757 free(conf->npn_str);
2758
2759 /* the NPN string is built as a suite of (<len> <name>)* */
2760 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
2761 conf->npn_str = calloc(1, conf->npn_len);
2762 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
2763
2764 /* replace commas with the name length */
2765 p1 = conf->npn_str;
2766 p2 = p1 + 1;
2767 while (1) {
2768 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
2769 if (!p2)
2770 p2 = p1 + 1 + strlen(p1 + 1);
2771
2772 if (p2 - (p1 + 1) > 255) {
2773 *p2 = '\0';
2774 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2775 return ERR_ALERT | ERR_FATAL;
2776 }
2777
2778 *p1 = p2 - (p1 + 1);
2779 p1 = p2;
2780
2781 if (!*p2)
2782 break;
2783
2784 *(p2++) = '\0';
2785 }
2786 return 0;
2787#else
2788 if (err)
2789 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
2790 return ERR_ALERT | ERR_FATAL;
2791#endif
2792}
2793
Willy Tarreauab861d32013-04-02 02:30:41 +02002794/* parse the "alpn" bind keyword */
2795static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2796{
2797#ifdef OPENSSL_ALPN_NEGOTIATED
2798 char *p1, *p2;
2799
2800 if (!*args[cur_arg + 1]) {
2801 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
2802 return ERR_ALERT | ERR_FATAL;
2803 }
2804
2805 free(conf->alpn_str);
2806
2807 /* the ALPN string is built as a suite of (<len> <name>)* */
2808 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
2809 conf->alpn_str = calloc(1, conf->alpn_len);
2810 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
2811
2812 /* replace commas with the name length */
2813 p1 = conf->alpn_str;
2814 p2 = p1 + 1;
2815 while (1) {
2816 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
2817 if (!p2)
2818 p2 = p1 + 1 + strlen(p1 + 1);
2819
2820 if (p2 - (p1 + 1) > 255) {
2821 *p2 = '\0';
2822 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2823 return ERR_ALERT | ERR_FATAL;
2824 }
2825
2826 *p1 = p2 - (p1 + 1);
2827 p1 = p2;
2828
2829 if (!*p2)
2830 break;
2831
2832 *(p2++) = '\0';
2833 }
2834 return 0;
2835#else
2836 if (err)
2837 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
2838 return ERR_ALERT | ERR_FATAL;
2839#endif
2840}
2841
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002842/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002843static 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 +02002844{
Willy Tarreau81796be2012-09-22 19:11:47 +02002845 struct listener *l;
2846
Willy Tarreau4348fad2012-09-20 16:48:07 +02002847 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02002848
2849 if (global.listen_default_ciphers && !conf->ciphers)
2850 conf->ciphers = strdup(global.listen_default_ciphers);
2851
Willy Tarreau81796be2012-09-22 19:11:47 +02002852 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002853 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02002854
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002855 return 0;
2856}
2857
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002858/* parse the "strict-sni" bind keyword */
2859static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2860{
2861 conf->strict_sni = 1;
2862 return 0;
2863}
2864
Emeric Brund94b3fe2012-09-20 18:23:56 +02002865/* parse the "verify" bind keyword */
2866static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2867{
2868 if (!*args[cur_arg + 1]) {
2869 if (err)
2870 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
2871 return ERR_ALERT | ERR_FATAL;
2872 }
2873
2874 if (strcmp(args[cur_arg + 1], "none") == 0)
2875 conf->verify = SSL_VERIFY_NONE;
2876 else if (strcmp(args[cur_arg + 1], "optional") == 0)
2877 conf->verify = SSL_VERIFY_PEER;
2878 else if (strcmp(args[cur_arg + 1], "required") == 0)
2879 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2880 else {
2881 if (err)
2882 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
2883 args[cur_arg], args[cur_arg + 1]);
2884 return ERR_ALERT | ERR_FATAL;
2885 }
2886
2887 return 0;
2888}
2889
Willy Tarreau92faadf2012-10-10 23:04:25 +02002890/************** "server" keywords ****************/
2891
Emeric Brunef42d922012-10-11 16:11:36 +02002892/* parse the "ca-file" server keyword */
2893static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2894{
2895 if (!*args[*cur_arg + 1]) {
2896 if (err)
2897 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
2898 return ERR_ALERT | ERR_FATAL;
2899 }
2900
2901 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2902 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2903 else
2904 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
2905
2906 return 0;
2907}
2908
Willy Tarreau92faadf2012-10-10 23:04:25 +02002909/* parse the "check-ssl" server keyword */
2910static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2911{
2912 newsrv->check.use_ssl = 1;
2913 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2914 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2915 return 0;
2916}
2917
2918/* parse the "ciphers" server keyword */
2919static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2920{
2921 if (!*args[*cur_arg + 1]) {
2922 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
2923 return ERR_ALERT | ERR_FATAL;
2924 }
2925
2926 free(newsrv->ssl_ctx.ciphers);
2927 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
2928 return 0;
2929}
2930
Emeric Brunef42d922012-10-11 16:11:36 +02002931/* parse the "crl-file" server keyword */
2932static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2933{
2934#ifndef X509_V_FLAG_CRL_CHECK
2935 if (err)
2936 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
2937 return ERR_ALERT | ERR_FATAL;
2938#else
2939 if (!*args[*cur_arg + 1]) {
2940 if (err)
2941 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
2942 return ERR_ALERT | ERR_FATAL;
2943 }
2944
2945 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2946 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2947 else
2948 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
2949
2950 return 0;
2951#endif
2952}
2953
Emeric Bruna7aa3092012-10-26 12:58:00 +02002954/* parse the "crt" server keyword */
2955static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2956{
2957 if (!*args[*cur_arg + 1]) {
2958 if (err)
2959 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
2960 return ERR_ALERT | ERR_FATAL;
2961 }
2962
2963 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
2964 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2965 else
2966 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
2967
2968 return 0;
2969}
Emeric Brunef42d922012-10-11 16:11:36 +02002970
Willy Tarreau92faadf2012-10-10 23:04:25 +02002971/* parse the "force-sslv3" server keyword */
2972static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2973{
2974 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
2975 return 0;
2976}
2977
2978/* parse the "force-tlsv10" server keyword */
2979static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2980{
2981 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
2982 return 0;
2983}
2984
2985/* parse the "force-tlsv11" server keyword */
2986static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2987{
2988#if SSL_OP_NO_TLSv1_1
2989 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
2990 return 0;
2991#else
2992 if (err)
2993 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
2994 return ERR_ALERT | ERR_FATAL;
2995#endif
2996}
2997
2998/* parse the "force-tlsv12" server keyword */
2999static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3000{
3001#if SSL_OP_NO_TLSv1_2
3002 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
3003 return 0;
3004#else
3005 if (err)
3006 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
3007 return ERR_ALERT | ERR_FATAL;
3008#endif
3009}
3010
3011/* parse the "no-sslv3" server keyword */
3012static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3013{
3014 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
3015 return 0;
3016}
3017
3018/* parse the "no-tlsv10" server keyword */
3019static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3020{
3021 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
3022 return 0;
3023}
3024
3025/* parse the "no-tlsv11" server keyword */
3026static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3027{
3028 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
3029 return 0;
3030}
3031
3032/* parse the "no-tlsv12" server keyword */
3033static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3034{
3035 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
3036 return 0;
3037}
3038
Emeric Brunf9c5c472012-10-11 15:28:34 +02003039/* parse the "no-tls-tickets" server keyword */
3040static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3041{
3042 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
3043 return 0;
3044}
3045
Willy Tarreau92faadf2012-10-10 23:04:25 +02003046/* parse the "ssl" server keyword */
3047static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3048{
3049 newsrv->use_ssl = 1;
3050 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3051 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3052 return 0;
3053}
3054
Emeric Brunef42d922012-10-11 16:11:36 +02003055/* parse the "verify" server keyword */
3056static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3057{
3058 if (!*args[*cur_arg + 1]) {
3059 if (err)
3060 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
3061 return ERR_ALERT | ERR_FATAL;
3062 }
3063
3064 if (strcmp(args[*cur_arg + 1], "none") == 0)
3065 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
3066 else if (strcmp(args[*cur_arg + 1], "required") == 0)
3067 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
3068 else {
3069 if (err)
3070 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
3071 args[*cur_arg], args[*cur_arg + 1]);
3072 return ERR_ALERT | ERR_FATAL;
3073 }
3074
3075 return 0;
3076}
3077
Willy Tarreau7875d092012-09-10 08:20:03 +02003078/* Note: must not be declared <const> as its list will be overwritten.
3079 * Please take care of keeping this list alphabetically sorted.
3080 */
3081static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
Willy Tarreau80aca902013-01-07 15:42:20 +01003082 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3083 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3084 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3085 { "ssl_c_i_dn", smp_fetch_ssl_c_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3086 { "ssl_c_key_alg", smp_fetch_ssl_c_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3087 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3088 { "ssl_c_notbefore", smp_fetch_ssl_c_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3089 { "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3090 { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3091 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
James Votha051b4a2013-05-14 20:37:59 +02003092 { "ssl_c_sha1", smp_fetch_ssl_c_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01003093 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3094 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3095 { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3096 { "ssl_f_i_dn", smp_fetch_ssl_f_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3097 { "ssl_f_key_alg", smp_fetch_ssl_f_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3098 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3099 { "ssl_f_notbefore", smp_fetch_ssl_f_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3100 { "ssl_f_sig_alg", smp_fetch_ssl_f_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3101 { "ssl_f_s_dn", smp_fetch_ssl_f_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3102 { "ssl_f_serial", smp_fetch_ssl_f_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3103 { "ssl_f_version", smp_fetch_ssl_f_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3104 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3105 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3106 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3107 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3108 { "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 +02003109#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau80aca902013-01-07 15:42:20 +01003110 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003111#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003112#ifdef OPENSSL_ALPN_NEGOTIATED
3113 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3114#endif
Willy Tarreau80aca902013-01-07 15:42:20 +01003115 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3116 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3117 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_CBIN, SMP_USE_L5CLI },
3118 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreau7875d092012-09-10 08:20:03 +02003119 { NULL, NULL, 0, 0, 0 },
3120}};
3121
3122/* Note: must not be declared <const> as its list will be overwritten.
3123 * Please take care of keeping this list alphabetically sorted.
3124 */
3125static struct acl_kw_list acl_kws = {{ },{
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003126 { "ssl_c_ca_err", NULL, acl_parse_int, acl_match_int },
3127 { "ssl_c_ca_err_depth", NULL, acl_parse_int, acl_match_int },
3128 { "ssl_c_err", NULL, acl_parse_int, acl_match_int },
3129 { "ssl_c_i_dn", NULL, acl_parse_str, acl_match_str },
3130 { "ssl_c_key_alg", NULL, acl_parse_str, acl_match_str },
3131 { "ssl_c_notafter", NULL, acl_parse_str, acl_match_str },
3132 { "ssl_c_notbefore", NULL, acl_parse_str, acl_match_str },
3133 { "ssl_c_sig_alg", NULL, acl_parse_str, acl_match_str },
3134 { "ssl_c_s_dn", NULL, acl_parse_str, acl_match_str },
3135 { "ssl_c_serial", NULL, acl_parse_bin, acl_match_bin },
3136 { "ssl_c_used", NULL, acl_parse_nothing, acl_match_nothing },
3137 { "ssl_c_verify", NULL, acl_parse_int, acl_match_int },
3138 { "ssl_c_version", NULL, acl_parse_int, acl_match_int },
3139 { "ssl_f_i_dn", NULL, acl_parse_str, acl_match_str },
3140 { "ssl_f_key_alg", NULL, acl_parse_str, acl_match_str },
3141 { "ssl_f_notafter", NULL, acl_parse_str, acl_match_str },
3142 { "ssl_f_notbefore", NULL, acl_parse_str, acl_match_str },
3143 { "ssl_f_sig_alg", NULL, acl_parse_str, acl_match_str },
3144 { "ssl_f_s_dn", NULL, acl_parse_str, acl_match_str },
3145 { "ssl_f_serial", NULL, acl_parse_bin, acl_match_bin },
3146 { "ssl_f_version", NULL, acl_parse_int, acl_match_int },
3147 { "ssl_fc", NULL, acl_parse_nothing, acl_match_nothing },
3148 { "ssl_fc_alg_keysize", NULL, acl_parse_int, acl_match_int },
3149 { "ssl_fc_cipher", NULL, acl_parse_str, acl_match_str },
3150 { "ssl_fc_has_crt", NULL, acl_parse_nothing, acl_match_nothing },
3151 { "ssl_fc_has_sni", NULL, acl_parse_nothing, acl_match_nothing },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003152#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003153 { "ssl_fc_npn", NULL, acl_parse_str, acl_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003154#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003155#ifdef OPENSSL_ALPN_NEGOTIATED
3156 { "ssl_fc_alpn", NULL, acl_parse_str, acl_match_str },
3157#endif
Willy Tarreaud86e29d2013-03-25 08:21:05 +01003158 { "ssl_fc_protocol", NULL, acl_parse_str, acl_match_str },
3159 { "ssl_fc_use_keysize", NULL, acl_parse_int, acl_match_int },
3160 { "ssl_fc_sni", "ssl_fc_sni", acl_parse_str, acl_match_str },
3161 { "ssl_fc_sni_end", "ssl_fc_sni", acl_parse_str, acl_match_end },
3162 { "ssl_fc_sni_reg", "ssl_fc_sni", acl_parse_reg, acl_match_reg },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01003163 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02003164}};
3165
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003166/* Note: must not be declared <const> as its list will be overwritten.
3167 * Please take care of keeping this list alphabetically sorted, doing so helps
3168 * all code contributors.
3169 * Optional keywords are also declared with a NULL ->parse() function so that
3170 * the config parser can report an appropriate error when a known keyword was
3171 * not enabled.
3172 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02003173static struct bind_kw_list bind_kws = { "SSL", { }, {
Willy Tarreauab861d32013-04-02 02:30:41 +02003174 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003175 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003176 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
3177 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003178 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003179 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
3180 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003181 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003182 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003183 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
3184 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
3185 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
3186 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02003187 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
3188 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
3189 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
3190 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003191 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003192 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003193 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003194 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003195 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003196 { NULL, NULL, 0 },
3197}};
Emeric Brun46591952012-05-18 15:47:34 +02003198
Willy Tarreau92faadf2012-10-10 23:04:25 +02003199/* Note: must not be declared <const> as its list will be overwritten.
3200 * Please take care of keeping this list alphabetically sorted, doing so helps
3201 * all code contributors.
3202 * Optional keywords are also declared with a NULL ->parse() function so that
3203 * the config parser can report an appropriate error when a known keyword was
3204 * not enabled.
3205 */
3206static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02003207 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003208 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
3209 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02003210 { "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 +02003211 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003212 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
3213 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
3214 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
3215 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
3216 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
3217 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
3218 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
3219 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02003220 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003221 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02003222 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Willy Tarreau92faadf2012-10-10 23:04:25 +02003223 { NULL, NULL, 0, 0 },
3224}};
3225
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003226/* transport-layer operations for SSL sockets */
3227struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02003228 .snd_buf = ssl_sock_from_buf,
3229 .rcv_buf = ssl_sock_to_buf,
3230 .rcv_pipe = NULL,
3231 .snd_pipe = NULL,
3232 .shutr = NULL,
3233 .shutw = ssl_sock_shutw,
3234 .close = ssl_sock_close,
3235 .init = ssl_sock_init,
3236};
3237
3238__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02003239static void __ssl_sock_init(void)
3240{
Emeric Brun46591952012-05-18 15:47:34 +02003241 STACK_OF(SSL_COMP)* cm;
3242
3243 SSL_library_init();
3244 cm = SSL_COMP_get_compression_methods();
3245 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02003246 sample_register_fetches(&sample_fetch_keywords);
3247 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003248 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02003249 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02003250}
3251
3252/*
3253 * Local variables:
3254 * c-indent-level: 8
3255 * c-basic-offset: 8
3256 * End:
3257 */