blob: 88c758b1dff552644eae25c133760bec74bc787a [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>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010069#include <proto/pattern.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020070#include <proto/server.h>
Emeric Brun46591952012-05-18 15:47:34 +020071#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +020072#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020073#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +020074#include <proto/ssl_sock.h>
75#include <proto/task.h>
76
Emeric Brune64aef12012-09-21 13:15:06 +020077#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brunf282a812012-09-21 15:27:54 +020078/* bits 0xFFFF0000 are reserved to store verify errors */
79
80/* Verify errors macros */
81#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
82#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
83#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
84
85#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
86#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
87#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +020088
Willy Tarreau71b734c2014-01-28 15:19:44 +010089int sslconns = 0;
90int totalsslconns = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +020091
92void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
93{
94 struct connection *conn = (struct connection *)SSL_get_app_data(ssl);
95 (void)ret; /* shut gcc stupid warning */
96
97 if (where & SSL_CB_HANDSHAKE_START) {
98 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreau20879a02012-12-03 16:32:10 +010099 if (conn->flags & CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +0200100 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +0100101 conn->err_code = CO_ER_SSL_RENEG;
102 }
Emeric Brune1f38db2012-09-03 20:36:47 +0200103 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200104}
105
Emeric Brune64aef12012-09-21 13:15:06 +0200106/* Callback is called for each certificate of the chain during a verify
107 ok is set to 1 if preverify detect no error on current certificate.
108 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -0700109int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +0200110{
111 SSL *ssl;
112 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +0200113 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +0200114
115 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
116 conn = (struct connection *)SSL_get_app_data(ssl);
117
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200118 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +0200119
Emeric Brun81c00f02012-09-21 14:31:21 +0200120 if (ok) /* no errors */
121 return ok;
122
123 depth = X509_STORE_CTX_get_error_depth(x_store);
124 err = X509_STORE_CTX_get_error(x_store);
125
126 /* check if CA error needs to be ignored */
127 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200128 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
129 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
130 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +0200131 }
132
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100133 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
134 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +0200135 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100136 }
Emeric Brun81c00f02012-09-21 14:31:21 +0200137
Willy Tarreau20879a02012-12-03 16:32:10 +0100138 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +0200139 return 0;
140 }
141
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200142 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
143 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +0200144
Emeric Brun81c00f02012-09-21 14:31:21 +0200145 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100146 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
147 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +0200148 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100149 }
Emeric Brun81c00f02012-09-21 14:31:21 +0200150
Willy Tarreau20879a02012-12-03 16:32:10 +0100151 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +0200152 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +0200153}
154
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200155#ifdef OPENSSL_NPN_NEGOTIATED
156/* This callback is used so that the server advertises the list of
157 * negociable protocols for NPN.
158 */
159static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
160 unsigned int *len, void *arg)
161{
162 struct bind_conf *conf = arg;
163
164 *data = (const unsigned char *)conf->npn_str;
165 *len = conf->npn_len;
166 return SSL_TLSEXT_ERR_OK;
167}
168#endif
169
Willy Tarreauab861d32013-04-02 02:30:41 +0200170#ifdef OPENSSL_ALPN_NEGOTIATED
171/* This callback is used so that the server advertises the list of
172 * negociable protocols for ALPN.
173 */
174static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **data,
175 unsigned int *len, void *arg)
176{
177 struct bind_conf *conf = arg;
178
179 *data = (const unsigned char *)conf->alpn_str;
180 *len = conf->alpn_len;
181 return SSL_TLSEXT_ERR_OK;
182}
183#endif
184
Emeric Brunfc0421f2012-09-07 17:30:07 +0200185#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
186/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
187 * warning when no match is found, which implies the default (first) cert
188 * will keep being used.
189 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200190static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, struct bind_conf *s)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200191{
192 const char *servername;
193 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200194 struct ebmb_node *node, *n;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200195 int i;
196 (void)al; /* shut gcc stupid warning */
197
198 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100199 if (!servername) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200200 return (s->strict_sni ?
201 SSL_TLSEXT_ERR_ALERT_FATAL :
Emmanuel Hocdet79274e22013-05-31 12:47:44 +0200202 SSL_TLSEXT_ERR_NOACK);
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100203 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200204
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100205 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200206 if (!servername[i])
207 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100208 trash.str[i] = tolower(servername[i]);
209 if (!wildp && (trash.str[i] == '.'))
210 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200211 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100212 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200213
214 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100215 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200216
217 /* lookup a not neg filter */
218 for (n = node; n; n = ebmb_next_dup(n)) {
219 if (!container_of(n, struct sni_ctx, name)->neg) {
220 node = n;
221 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100222 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200223 }
224 if (!node && wildp) {
225 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +0200226 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200227 }
228 if (!node || container_of(node, struct sni_ctx, name)->neg) {
229 return (s->strict_sni ?
230 SSL_TLSEXT_ERR_ALERT_FATAL :
231 SSL_TLSEXT_ERR_ALERT_WARNING);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200232 }
233
234 /* switch ctx */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200235 SSL_set_SSL_CTX(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200236 return SSL_TLSEXT_ERR_OK;
237}
238#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
239
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200240#ifndef OPENSSL_NO_DH
241/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
242 if an error occured, and 0 if parameter not found. */
243int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
244{
245 int ret = -1;
246 BIO *in;
247 DH *dh = NULL;
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200248 /* If not present, use parameters generated using 'openssl dhparam 1024 -C':
249 * -----BEGIN DH PARAMETERS-----
250 * MIGHAoGBAJJAJDXDoS5E03MNjnjK36eOL1tRqVa/9NuOVlI+lpXmPjJQbP65EvKn
251 * fSLnG7VMhoCJO4KtG88zf393ltP7loGB2bofcDSr+x+XsxBM8yA/Zj6BmQt+CQ9s
252 * TF7hoOV+wXTT6ErZ5y5qx9pq6hLfKXwTGFT78hrE6HnCO7xgtPdTAgEC
253 * -----END DH PARAMETERS-----
254 */
255 static const unsigned char dh1024_p[] = {
256 0x92, 0x40, 0x24, 0x35, 0xC3, 0xA1, 0x2E, 0x44, 0xD3, 0x73, 0x0D, 0x8E,
257 0x78, 0xCA, 0xDF, 0xA7, 0x8E, 0x2F, 0x5B, 0x51, 0xA9, 0x56, 0xBF, 0xF4,
258 0xDB, 0x8E, 0x56, 0x52, 0x3E, 0x96, 0x95, 0xE6, 0x3E, 0x32, 0x50, 0x6C,
259 0xFE, 0xB9, 0x12, 0xF2, 0xA7, 0x7D, 0x22, 0xE7, 0x1B, 0xB5, 0x4C, 0x86,
260 0x80, 0x89, 0x3B, 0x82, 0xAD, 0x1B, 0xCF, 0x33, 0x7F, 0x7F, 0x77, 0x96,
261 0xD3, 0xFB, 0x96, 0x81, 0x81, 0xD9, 0xBA, 0x1F, 0x70, 0x34, 0xAB, 0xFB,
262 0x1F, 0x97, 0xB3, 0x10, 0x4C, 0xF3, 0x20, 0x3F, 0x66, 0x3E, 0x81, 0x99,
263 0x0B, 0x7E, 0x09, 0x0F, 0x6C, 0x4C, 0x5E, 0xE1, 0xA0, 0xE5, 0x7E, 0xC1,
264 0x74, 0xD3, 0xE8, 0x4A, 0xD9, 0xE7, 0x2E, 0x6A, 0xC7, 0xDA, 0x6A, 0xEA,
265 0x12, 0xDF, 0x29, 0x7C, 0x13, 0x18, 0x54, 0xFB, 0xF2, 0x1A, 0xC4, 0xE8,
266 0x79, 0xC2, 0x3B, 0xBC, 0x60, 0xB4, 0xF7, 0x53,
267 };
268 static const unsigned char dh1024_g[] = {
269 0x02,
270 };
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200271
272 in = BIO_new(BIO_s_file());
273 if (in == NULL)
274 goto end;
275
276 if (BIO_read_filename(in, file) <= 0)
277 goto end;
278
279 dh = PEM_read_bio_DHparams(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200280 if (!dh) {
281 /* Clear openssl global errors stack */
282 ERR_clear_error();
283
284 dh = DH_new();
285 if (dh == NULL)
286 goto end;
287
288 dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
289 if (dh->p == NULL)
290 goto end;
291
292 dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
293 if (dh->g == NULL)
294 goto end;
295
296 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200297 }
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200298 else
299 ret = 1;
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200300
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200301 SSL_CTX_set_tmp_dh(ctx, dh);
Emeric Brun644cde02012-12-14 11:21:13 +0100302
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200303end:
304 if (dh)
305 DH_free(dh);
306
307 if (in)
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200308 BIO_free(in);
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200309
310 return ret;
311}
312#endif
313
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200314static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100315{
316 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200317 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100318
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200319 if (*name == '!') {
320 neg = 1;
321 name++;
322 }
323 if (*name == '*') {
324 wild = 1;
325 name++;
326 }
327 /* !* filter is a nop */
328 if (neg && wild)
329 return order;
330 if (*name) {
331 int j, len;
332 len = strlen(name);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100333 sc = malloc(sizeof(struct sni_ctx) + len + 1);
334 for (j = 0; j < len; j++)
335 sc->name.key[j] = tolower(name[j]);
336 sc->name.key[len] = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100337 sc->ctx = ctx;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200338 sc->order = order++;
339 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100340 if (wild)
341 ebst_insert(&s->sni_w_ctx, &sc->name);
342 else
343 ebst_insert(&s->sni_ctx, &sc->name);
344 }
345 return order;
346}
347
Emeric Brunfc0421f2012-09-07 17:30:07 +0200348/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
349 * an early error happens and the caller must call SSL_CTX_free() by itelf.
350 */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200351static 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 +0200352{
353 BIO *in;
354 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200355 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200356 int ret = -1;
357 int order = 0;
358 X509_NAME *xname;
359 char *str;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200360#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
361 STACK_OF(GENERAL_NAME) *names;
362#endif
363
364 in = BIO_new(BIO_s_file());
365 if (in == NULL)
366 goto end;
367
368 if (BIO_read_filename(in, file) <= 0)
369 goto end;
370
371 x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
372 if (x == NULL)
373 goto end;
374
Emeric Brun50bcecc2013-04-22 13:05:23 +0200375 if (fcount) {
376 while (fcount--)
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200377 order = ssl_sock_add_cert_sni(ctx, s, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100378 }
379 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200380#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100381 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
382 if (names) {
383 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
384 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
385 if (name->type == GEN_DNS) {
386 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200387 order = ssl_sock_add_cert_sni(ctx, s, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100388 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200389 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200390 }
391 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100392 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200393 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200394#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100395 xname = X509_get_subject_name(x);
396 i = -1;
397 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
398 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
399 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200400 order = ssl_sock_add_cert_sni(ctx, s, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100401 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200402 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200403 }
404 }
405
406 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
407 if (!SSL_CTX_use_certificate(ctx, x))
408 goto end;
409
410 if (ctx->extra_certs != NULL) {
411 sk_X509_pop_free(ctx->extra_certs, X509_free);
412 ctx->extra_certs = NULL;
413 }
414
415 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata))) {
416 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
417 X509_free(ca);
418 goto end;
419 }
420 }
421
422 err = ERR_get_error();
423 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
424 /* we successfully reached the last cert in the file */
425 ret = 1;
426 }
427 ERR_clear_error();
428
429end:
430 if (x)
431 X509_free(x);
432
433 if (in)
434 BIO_free(in);
435
436 return ret;
437}
438
Emeric Brun50bcecc2013-04-22 13:05:23 +0200439static 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 +0200440{
441 int ret;
442 SSL_CTX *ctx;
443
444 ctx = SSL_CTX_new(SSLv23_server_method());
445 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200446 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
447 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200448 return 1;
449 }
450
451 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200452 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
453 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200454 SSL_CTX_free(ctx);
455 return 1;
456 }
457
Emeric Brun50bcecc2013-04-22 13:05:23 +0200458 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200459 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200460 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
461 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200462 if (ret < 0) /* serious error, must do that ourselves */
463 SSL_CTX_free(ctx);
464 return 1;
465 }
Emeric Brun61694ab2012-10-26 13:35:33 +0200466
467 if (SSL_CTX_check_private_key(ctx) <= 0) {
468 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
469 err && *err ? *err : "", path);
470 return 1;
471 }
472
Emeric Brunfc0421f2012-09-07 17:30:07 +0200473 /* we must not free the SSL_CTX anymore below, since it's already in
474 * the tree, so it will be discovered and cleaned in time.
475 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200476#ifndef OPENSSL_NO_DH
477 ret = ssl_sock_load_dh_params(ctx, path);
478 if (ret < 0) {
479 if (err)
480 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
481 *err ? *err : "", path);
482 return 1;
483 }
484#endif
485
Emeric Brunfc0421f2012-09-07 17:30:07 +0200486#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200487 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200488 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
489 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +0200490 return 1;
491 }
492#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200493 if (!bind_conf->default_ctx)
494 bind_conf->default_ctx = ctx;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200495
496 return 0;
497}
498
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200499int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200500{
501 struct dirent *de;
502 DIR *dir;
503 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +0100504 char *end;
505 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200506 int cfgerr = 0;
507
508 if (!(dir = opendir(path)))
Emeric Brun50bcecc2013-04-22 13:05:23 +0200509 return ssl_sock_load_cert_file(path, bind_conf, curproxy, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200510
511 /* strip trailing slashes, including first one */
512 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
513 *end = 0;
514
Emeric Brunfc0421f2012-09-07 17:30:07 +0200515 while ((de = readdir(dir))) {
Willy Tarreauee2663b2012-12-06 11:36:59 +0100516 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200517 if (stat(fp, &buf) != 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200518 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
519 err && *err ? *err : "", fp, strerror(errno));
Emeric Brunfc0421f2012-09-07 17:30:07 +0200520 cfgerr++;
521 continue;
522 }
523 if (!S_ISREG(buf.st_mode))
524 continue;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200525 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, curproxy, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200526 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200527 closedir(dir);
528 return cfgerr;
529}
530
Thierry Fournier383085f2013-01-24 14:15:43 +0100531/* Make sure openssl opens /dev/urandom before the chroot. The work is only
532 * done once. Zero is returned if the operation fails. No error is returned
533 * if the random is said as not implemented, because we expect that openssl
534 * will use another method once needed.
535 */
536static int ssl_initialize_random()
537{
538 unsigned char random;
539 static int random_initialized = 0;
540
541 if (!random_initialized && RAND_bytes(&random, 1) != 0)
542 random_initialized = 1;
543
544 return random_initialized;
545}
546
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100547int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
548{
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200549 char thisline[LINESIZE];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100550 FILE *f;
551 int linenum = 0;
552 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100553
Willy Tarreauad1731d2013-04-02 17:35:58 +0200554 if ((f = fopen(file, "r")) == NULL) {
555 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100556 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200557 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100558
559 while (fgets(thisline, sizeof(thisline), f) != NULL) {
560 int arg;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200561 int newarg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100562 char *end;
563 char *args[MAX_LINE_ARGS + 1];
564 char *line = thisline;
565
566 linenum++;
567 end = line + strlen(line);
568 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
569 /* Check if we reached the limit and the last char is not \n.
570 * Watch out for the last line without the terminating '\n'!
571 */
Willy Tarreauad1731d2013-04-02 17:35:58 +0200572 memprintf(err, "line %d too long in file '%s', limit is %d characters",
573 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100574 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200575 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100576 }
577
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100578 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200579 newarg = 1;
580 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100581 if (*line == '#' || *line == '\n' || *line == '\r') {
582 /* end of string, end of loop */
583 *line = 0;
584 break;
585 }
586 else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +0200587 newarg = 1;
588 *line = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100589 }
Emeric Brun50bcecc2013-04-22 13:05:23 +0200590 else if (newarg) {
591 if (arg == MAX_LINE_ARGS) {
592 memprintf(err, "too many args on line %d in file '%s'.",
593 linenum, file);
594 cfgerr = 1;
595 break;
596 }
597 newarg = 0;
598 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100599 }
Emeric Brun50bcecc2013-04-22 13:05:23 +0200600 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100601 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200602 if (cfgerr)
603 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200604
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100605 /* empty line */
Emeric Brun50bcecc2013-04-22 13:05:23 +0200606 if (!arg)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100607 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100608
Emeric Brun50bcecc2013-04-22 13:05:23 +0200609 cfgerr = ssl_sock_load_cert_file(args[0], bind_conf, curproxy, &args[1], arg-1, err);
Willy Tarreauad1731d2013-04-02 17:35:58 +0200610 if (cfgerr) {
611 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100612 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200613 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100614 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100615 fclose(f);
616 return cfgerr;
617}
618
Emeric Brunfc0421f2012-09-07 17:30:07 +0200619#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
620#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
621#endif
622
623#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
624#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
Willy Tarreau7d588ee2012-11-26 18:47:31 +0100625#define SSL_renegotiate_pending(arg) 0
Emeric Brunfc0421f2012-09-07 17:30:07 +0200626#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200627#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
628#define SSL_OP_SINGLE_ECDH_USE 0
629#endif
Emeric Brun2d0c4822012-10-02 13:45:20 +0200630#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
631#define SSL_OP_NO_TICKET 0
632#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200633#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
634#define SSL_OP_NO_COMPRESSION 0
635#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +0200636#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
637#define SSL_OP_NO_TLSv1_1 0
638#endif
639#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
640#define SSL_OP_NO_TLSv1_2 0
641#endif
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200642#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
643#define SSL_OP_SINGLE_DH_USE 0
644#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200645#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
646#define SSL_OP_SINGLE_ECDH_USE 0
647#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200648#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
649#define SSL_MODE_RELEASE_BUFFERS 0
650#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200651int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy *curproxy)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200652{
653 int cfgerr = 0;
654 int ssloptions =
655 SSL_OP_ALL | /* all known workarounds for bugs */
656 SSL_OP_NO_SSLv2 |
657 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200658 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +0200659 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +0200660 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
661 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200662 int sslmode =
663 SSL_MODE_ENABLE_PARTIAL_WRITE |
664 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
665 SSL_MODE_RELEASE_BUFFERS;
666
Thierry Fournier383085f2013-01-24 14:15:43 +0100667 /* Make sure openssl opens /dev/urandom before the chroot */
668 if (!ssl_initialize_random()) {
669 Alert("OpenSSL random data generator initialization failed.\n");
670 cfgerr++;
671 }
672
Emeric Brun89675492012-10-05 13:48:26 +0200673 if (bind_conf->ssl_options & BC_SSL_O_NO_SSLV3)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200674 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brun89675492012-10-05 13:48:26 +0200675 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV10)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200676 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun89675492012-10-05 13:48:26 +0200677 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV11)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200678 ssloptions |= SSL_OP_NO_TLSv1_1;
Emeric Brun89675492012-10-05 13:48:26 +0200679 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV12)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200680 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun89675492012-10-05 13:48:26 +0200681 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
Emeric Brun2d0c4822012-10-02 13:45:20 +0200682 ssloptions |= SSL_OP_NO_TICKET;
Emeric Brun2cb7ae52012-10-05 14:14:21 +0200683 if (bind_conf->ssl_options & BC_SSL_O_USE_SSLV3)
684 SSL_CTX_set_ssl_version(ctx, SSLv3_server_method());
685 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV10)
686 SSL_CTX_set_ssl_version(ctx, TLSv1_server_method());
687#if SSL_OP_NO_TLSv1_1
688 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV11)
689 SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method());
690#endif
691#if SSL_OP_NO_TLSv1_2
692 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV12)
693 SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method());
694#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200695
696 SSL_CTX_set_options(ctx, ssloptions);
697 SSL_CTX_set_mode(ctx, sslmode);
Evan Broderbe554312013-06-27 00:05:25 -0700698 SSL_CTX_set_verify(ctx, bind_conf->verify ? bind_conf->verify : SSL_VERIFY_NONE, ssl_sock_bind_verifycbk);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200699 if (bind_conf->verify & SSL_VERIFY_PEER) {
Emeric Brunfb510ea2012-10-05 12:00:26 +0200700 if (bind_conf->ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200701 /* load CAfile to verify */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200702 if (!SSL_CTX_load_verify_locations(ctx, bind_conf->ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200703 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200704 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200705 cfgerr++;
706 }
707 /* set CA names fo client cert request, function returns void */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200708 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(bind_conf->ca_file));
Emeric Brund94b3fe2012-09-20 18:23:56 +0200709 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200710#ifdef X509_V_FLAG_CRL_CHECK
Emeric Brunfb510ea2012-10-05 12:00:26 +0200711 if (bind_conf->crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200712 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
713
Emeric Brunfb510ea2012-10-05 12:00:26 +0200714 if (!store || !X509_STORE_load_locations(store, bind_conf->crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200715 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200716 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200717 cfgerr++;
718 }
Emeric Brun561e5742012-10-02 15:20:55 +0200719 else {
720 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
721 }
Emeric Brund94b3fe2012-09-20 18:23:56 +0200722 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200723#endif
Emeric Brun644cde02012-12-14 11:21:13 +0100724 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +0200725 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200726
Emeric Brun4f65bff2012-11-16 15:11:00 +0100727 if (global.tune.ssllifetime)
728 SSL_CTX_set_timeout(ctx, global.tune.ssllifetime);
729
Emeric Brunfc0421f2012-09-07 17:30:07 +0200730 shared_context_set_cache(ctx);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200731 if (bind_conf->ciphers &&
732 !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200733 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 +0200734 curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200735 cfgerr++;
736 }
737
738 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200739#ifdef OPENSSL_NPN_NEGOTIATED
740 if (bind_conf->npn_str)
741 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
742#endif
Willy Tarreauab861d32013-04-02 02:30:41 +0200743#ifdef OPENSSL_ALPN_NEGOTIATED
744 if (bind_conf->alpn_str)
745 SSL_CTX_set_alpn_advertised_cb(ctx, ssl_sock_advertise_alpn_protos, bind_conf);
746#endif
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200747
Emeric Brunfc0421f2012-09-07 17:30:07 +0200748#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
749 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200750 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200751#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200752#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emeric Brun6924ef82013-03-06 14:08:53 +0100753 {
Emeric Brun2b58d042012-09-20 17:10:03 +0200754 int i;
755 EC_KEY *ecdh;
756
Emeric Brun6924ef82013-03-06 14:08:53 +0100757 i = OBJ_sn2nid(bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE);
Emeric Brun2b58d042012-09-20 17:10:03 +0200758 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
759 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 +0100760 curproxy->id, bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE,
761 bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +0200762 cfgerr++;
763 }
764 else {
765 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
766 EC_KEY_free(ecdh);
767 }
768 }
769#endif
770
Emeric Brunfc0421f2012-09-07 17:30:07 +0200771 return cfgerr;
772}
773
Evan Broderbe554312013-06-27 00:05:25 -0700774static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
775{
776 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
777 size_t prefixlen, suffixlen;
778
779 /* Trivial case */
780 if (strcmp(pattern, hostname) == 0)
781 return 1;
782
Evan Broderbe554312013-06-27 00:05:25 -0700783 /* The rest of this logic is based on RFC 6125, section 6.4.3
784 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
785
Emeric Bruna848dae2013-10-08 11:27:28 +0200786 pattern_wildcard = NULL;
787 pattern_left_label_end = pattern;
788 while (*pattern_left_label_end != '.') {
789 switch (*pattern_left_label_end) {
790 case 0:
791 /* End of label not found */
792 return 0;
793 case '*':
794 /* If there is more than one wildcards */
795 if (pattern_wildcard)
796 return 0;
797 pattern_wildcard = pattern_left_label_end;
798 break;
799 }
800 pattern_left_label_end++;
801 }
802
803 /* If it's not trivial and there is no wildcard, it can't
804 * match */
805 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -0700806 return 0;
807
808 /* Make sure all labels match except the leftmost */
809 hostname_left_label_end = strchr(hostname, '.');
810 if (!hostname_left_label_end
811 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
812 return 0;
813
814 /* Make sure the leftmost label of the hostname is long enough
815 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +0200816 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -0700817 return 0;
818
819 /* Finally compare the string on either side of the
820 * wildcard */
821 prefixlen = pattern_wildcard - pattern;
822 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +0200823 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
824 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -0700825 return 0;
826
827 return 1;
828}
829
830static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
831{
832 SSL *ssl;
833 struct connection *conn;
834 char *servername;
835
836 int depth;
837 X509 *cert;
838 STACK_OF(GENERAL_NAME) *alt_names;
839 int i;
840 X509_NAME *cert_subject;
841 char *str;
842
843 if (ok == 0)
844 return ok;
845
846 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
847 conn = (struct connection *)SSL_get_app_data(ssl);
848
849 servername = objt_server(conn->target)->ssl_ctx.verify_host;
850
851 /* We only need to verify the CN on the actual server cert,
852 * not the indirect CAs */
853 depth = X509_STORE_CTX_get_error_depth(ctx);
854 if (depth != 0)
855 return ok;
856
857 /* At this point, the cert is *not* OK unless we can find a
858 * hostname match */
859 ok = 0;
860
861 cert = X509_STORE_CTX_get_current_cert(ctx);
862 /* It seems like this might happen if verify peer isn't set */
863 if (!cert)
864 return ok;
865
866 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
867 if (alt_names) {
868 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
869 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
870 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +0200871#if OPENSSL_VERSION_NUMBER < 0x00907000L
872 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
873#else
Evan Broderbe554312013-06-27 00:05:25 -0700874 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +0200875#endif
Evan Broderbe554312013-06-27 00:05:25 -0700876 ok = ssl_sock_srv_hostcheck(str, servername);
877 OPENSSL_free(str);
878 }
879 }
880 }
Emeric Brun4ad50a42013-09-17 15:19:54 +0200881 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -0700882 }
883
884 cert_subject = X509_get_subject_name(cert);
885 i = -1;
886 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
887 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
888 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
889 ok = ssl_sock_srv_hostcheck(str, servername);
890 OPENSSL_free(str);
891 }
892 }
893
894 return ok;
895}
896
Emeric Brun94324a42012-10-11 14:00:19 +0200897/* prepare ssl context from servers options. Returns an error count */
898int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
899{
900 int cfgerr = 0;
901 int options =
902 SSL_OP_ALL | /* all known workarounds for bugs */
903 SSL_OP_NO_SSLv2 |
904 SSL_OP_NO_COMPRESSION;
905 int mode =
906 SSL_MODE_ENABLE_PARTIAL_WRITE |
907 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
908 SSL_MODE_RELEASE_BUFFERS;
909
Thierry Fournier383085f2013-01-24 14:15:43 +0100910 /* Make sure openssl opens /dev/urandom before the chroot */
911 if (!ssl_initialize_random()) {
912 Alert("OpenSSL random data generator initialization failed.\n");
913 cfgerr++;
914 }
915
Emeric Brun94324a42012-10-11 14:00:19 +0200916 /* Initiate SSL context for current server */
917 srv->ssl_ctx.reused_sess = NULL;
918 if (srv->use_ssl)
919 srv->xprt = &ssl_sock;
920 if (srv->check.use_ssl)
Simon Horman66183002013-02-23 10:16:43 +0900921 srv->check_common.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +0200922
923 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
924 if (!srv->ssl_ctx.ctx) {
925 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
926 proxy_type_str(curproxy), curproxy->id,
927 srv->id);
928 cfgerr++;
929 return cfgerr;
930 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200931 if (srv->ssl_ctx.client_crt) {
932 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
933 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
934 proxy_type_str(curproxy), curproxy->id,
935 srv->id, srv->ssl_ctx.client_crt);
936 cfgerr++;
937 }
938 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
939 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
940 proxy_type_str(curproxy), curproxy->id,
941 srv->id, srv->ssl_ctx.client_crt);
942 cfgerr++;
943 }
944 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
945 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
946 proxy_type_str(curproxy), curproxy->id,
947 srv->id, srv->ssl_ctx.client_crt);
948 cfgerr++;
949 }
950 }
Emeric Brun94324a42012-10-11 14:00:19 +0200951
952 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
953 options |= SSL_OP_NO_SSLv3;
954 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
955 options |= SSL_OP_NO_TLSv1;
956 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
957 options |= SSL_OP_NO_TLSv1_1;
958 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
959 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200960 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
961 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200962 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
963 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
964 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
965 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
966#if SSL_OP_NO_TLSv1_1
967 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
968 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
969#endif
970#if SSL_OP_NO_TLSv1_2
971 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
972 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
973#endif
974
975 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
976 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Evan Broderbe554312013-06-27 00:05:25 -0700977 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
978 srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE,
979 srv->ssl_ctx.verify_host ? ssl_sock_srv_verifycbk : NULL);
Emeric Brunef42d922012-10-11 16:11:36 +0200980 if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
981 if (srv->ssl_ctx.ca_file) {
982 /* load CAfile to verify */
983 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
984 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
985 curproxy->id, srv->id,
986 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
987 cfgerr++;
988 }
989 }
990#ifdef X509_V_FLAG_CRL_CHECK
991 if (srv->ssl_ctx.crl_file) {
992 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
993
994 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
995 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
996 curproxy->id, srv->id,
997 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
998 cfgerr++;
999 }
1000 else {
1001 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
1002 }
1003 }
1004#endif
1005 }
1006
Emeric Brun4f65bff2012-11-16 15:11:00 +01001007 if (global.tune.ssllifetime)
1008 SSL_CTX_set_timeout(srv->ssl_ctx.ctx, global.tune.ssllifetime);
1009
Emeric Brun94324a42012-10-11 14:00:19 +02001010 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
1011 if (srv->ssl_ctx.ciphers &&
1012 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
1013 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
1014 curproxy->id, srv->id,
1015 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
1016 cfgerr++;
1017 }
1018
1019 return cfgerr;
1020}
1021
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001022/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02001023 * be NULL, in which case nothing is done. Returns the number of errors
1024 * encountered.
1025 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001026int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001027{
1028 struct ebmb_node *node;
1029 struct sni_ctx *sni;
1030 int err = 0;
1031
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001032 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001033 return 0;
1034
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001035 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001036 while (node) {
1037 sni = ebmb_entry(node, struct sni_ctx, name);
1038 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001039 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001040 node = ebmb_next(node);
1041 }
1042
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001043 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001044 while (node) {
1045 sni = ebmb_entry(node, struct sni_ctx, name);
1046 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001047 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001048 node = ebmb_next(node);
1049 }
1050 return err;
1051}
1052
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001053/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02001054 * be NULL, in which case nothing is done. The default_ctx is nullified too.
1055 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001056void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001057{
1058 struct ebmb_node *node, *back;
1059 struct sni_ctx *sni;
1060
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001061 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001062 return;
1063
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001064 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001065 while (node) {
1066 sni = ebmb_entry(node, struct sni_ctx, name);
1067 back = ebmb_next(node);
1068 ebmb_delete(node);
1069 if (!sni->order) /* only free the CTX on its first occurrence */
1070 SSL_CTX_free(sni->ctx);
1071 free(sni);
1072 node = back;
1073 }
1074
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001075 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001076 while (node) {
1077 sni = ebmb_entry(node, struct sni_ctx, name);
1078 back = ebmb_next(node);
1079 ebmb_delete(node);
1080 if (!sni->order) /* only free the CTX on its first occurrence */
1081 SSL_CTX_free(sni->ctx);
1082 free(sni);
1083 node = back;
1084 }
1085
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001086 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02001087}
1088
Emeric Brun46591952012-05-18 15:47:34 +02001089/*
1090 * This function is called if SSL * context is not yet allocated. The function
1091 * is designed to be called before any other data-layer operation and sets the
1092 * handshake flag on the connection. It is safe to call it multiple times.
1093 * It returns 0 on success and -1 in error case.
1094 */
1095static int ssl_sock_init(struct connection *conn)
1096{
1097 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001098 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001099 return 0;
1100
Willy Tarreau3c728722014-01-23 13:50:42 +01001101 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02001102 return 0;
1103
Willy Tarreau20879a02012-12-03 16:32:10 +01001104 if (global.maxsslconn && sslconns >= global.maxsslconn) {
1105 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02001106 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001107 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001108
Emeric Brun46591952012-05-18 15:47:34 +02001109 /* If it is in client mode initiate SSL session
1110 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001111 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001112 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001113 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001114 if (!conn->xprt_ctx) {
1115 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001116 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001117 }
Emeric Brun46591952012-05-18 15:47:34 +02001118
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001119 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001120 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1121 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001122
1123 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001124 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001125
Evan Broderbe554312013-06-27 00:05:25 -07001126 /* set connection pointer */
1127 SSL_set_app_data(conn->xprt_ctx, conn);
1128
Emeric Brun46591952012-05-18 15:47:34 +02001129 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001130 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001131
1132 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01001133 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001134 return 0;
1135 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001136 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001137 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001138 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001139 if (!conn->xprt_ctx) {
1140 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001141 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001142 }
Emeric Brun46591952012-05-18 15:47:34 +02001143
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001144 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001145
1146 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001147 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001148
Emeric Brune1f38db2012-09-03 20:36:47 +02001149 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001150 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +02001151
Emeric Brun46591952012-05-18 15:47:34 +02001152 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001153 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001154
1155 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01001156 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001157 return 0;
1158 }
1159 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01001160 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02001161 return -1;
1162}
1163
1164
1165/* This is the callback which is used when an SSL handshake is pending. It
1166 * updates the FD status if it wants some polling before being called again.
1167 * It returns 0 if it fails in a fatal way or needs to poll to go further,
1168 * otherwise it returns non-zero and removes itself from the connection's
1169 * flags (the bit is provided in <flag> by the caller).
1170 */
1171int ssl_sock_handshake(struct connection *conn, unsigned int flag)
1172{
1173 int ret;
1174
Willy Tarreau3c728722014-01-23 13:50:42 +01001175 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02001176 return 0;
1177
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001178 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001179 goto out_error;
1180
Emeric Brun674b7432012-11-08 19:21:55 +01001181 /* If we use SSL_do_handshake to process a reneg initiated by
1182 * the remote peer, it sometimes returns SSL_ERROR_SSL.
1183 * Usually SSL_write and SSL_read are used and process implicitly
1184 * the reneg handshake.
1185 * Here we use SSL_peek as a workaround for reneg.
1186 */
1187 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
1188 char c;
1189
1190 ret = SSL_peek(conn->xprt_ctx, &c, 1);
1191 if (ret <= 0) {
1192 /* handshake may have not been completed, let's find why */
1193 ret = SSL_get_error(conn->xprt_ctx, ret);
1194 if (ret == SSL_ERROR_WANT_WRITE) {
1195 /* SSL handshake needs to write, L4 connection may not be ready */
1196 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001197 __conn_sock_want_send(conn);
1198 fd_cant_send(conn->t.sock.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01001199 return 0;
1200 }
1201 else if (ret == SSL_ERROR_WANT_READ) {
1202 /* handshake may have been completed but we have
1203 * no more data to read.
1204 */
1205 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
1206 ret = 1;
1207 goto reneg_ok;
1208 }
1209 /* SSL handshake needs to read, L4 connection is ready */
1210 if (conn->flags & CO_FL_WAIT_L4_CONN)
1211 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1212 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001213 __conn_sock_want_recv(conn);
1214 fd_cant_recv(conn->t.sock.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01001215 return 0;
1216 }
1217 else if (ret == SSL_ERROR_SYSCALL) {
1218 /* if errno is null, then connection was successfully established */
1219 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1220 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001221 if (!conn->err_code) {
1222 if (!((SSL *)conn->xprt_ctx)->packet_length)
1223 if (!errno)
1224 conn->err_code = CO_ER_SSL_EMPTY;
1225 else
1226 conn->err_code = CO_ER_SSL_ABORT;
1227 else
1228 conn->err_code = CO_ER_SSL_HANDSHAKE;
1229 }
Emeric Brun674b7432012-11-08 19:21:55 +01001230 goto out_error;
1231 }
1232 else {
1233 /* Fail on all other handshake errors */
1234 /* Note: OpenSSL may leave unread bytes in the socket's
1235 * buffer, causing an RST to be emitted upon close() on
1236 * TCP sockets. We first try to drain possibly pending
1237 * data to avoid this as much as possible.
1238 */
Willy Tarreau46be2e52014-01-20 12:10:52 +01001239 conn_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01001240 if (!conn->err_code)
1241 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01001242 goto out_error;
1243 }
1244 }
1245 /* read some data: consider handshake completed */
1246 goto reneg_ok;
1247 }
1248
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001249 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001250 if (ret != 1) {
1251 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001252 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001253
1254 if (ret == SSL_ERROR_WANT_WRITE) {
1255 /* SSL handshake needs to write, L4 connection may not be ready */
1256 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001257 __conn_sock_want_send(conn);
1258 fd_cant_send(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001259 return 0;
1260 }
1261 else if (ret == SSL_ERROR_WANT_READ) {
1262 /* SSL handshake needs to read, L4 connection is ready */
1263 if (conn->flags & CO_FL_WAIT_L4_CONN)
1264 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1265 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001266 __conn_sock_want_recv(conn);
1267 fd_cant_recv(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001268 return 0;
1269 }
Willy Tarreau89230192012-09-28 20:22:13 +02001270 else if (ret == SSL_ERROR_SYSCALL) {
1271 /* if errno is null, then connection was successfully established */
1272 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1273 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001274
1275 if (!((SSL *)conn->xprt_ctx)->packet_length)
1276 if (!errno)
1277 conn->err_code = CO_ER_SSL_EMPTY;
1278 else
1279 conn->err_code = CO_ER_SSL_ABORT;
1280 else
1281 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +02001282 goto out_error;
1283 }
Emeric Brun46591952012-05-18 15:47:34 +02001284 else {
1285 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02001286 /* Note: OpenSSL may leave unread bytes in the socket's
1287 * buffer, causing an RST to be emitted upon close() on
1288 * TCP sockets. We first try to drain possibly pending
1289 * data to avoid this as much as possible.
1290 */
Willy Tarreau46be2e52014-01-20 12:10:52 +01001291 conn_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01001292 if (!conn->err_code)
1293 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001294 goto out_error;
1295 }
1296 }
1297
Emeric Brun674b7432012-11-08 19:21:55 +01001298reneg_ok:
1299
Emeric Brun46591952012-05-18 15:47:34 +02001300 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001301 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001302 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +02001303 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001304 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1305 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001306
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001307 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001308 }
1309 }
1310
1311 /* The connection is now established at both layers, it's time to leave */
1312 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1313 return 1;
1314
1315 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001316 /* Clear openssl global errors stack */
1317 ERR_clear_error();
1318
Emeric Brun9fa89732012-10-04 17:09:56 +02001319 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001320 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1321 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1322 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001323 }
1324
Emeric Brun46591952012-05-18 15:47:34 +02001325 /* Fail on all other handshake errors */
1326 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001327 if (!conn->err_code)
1328 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001329 return 0;
1330}
1331
1332/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01001333 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02001334 * buffer wraps, in which case a second call may be performed. The connection's
1335 * flags are updated with whatever special event is detected (error, read0,
1336 * empty). The caller is responsible for taking care of those events and
1337 * avoiding the call if inappropriate. The function does not call the
1338 * connection's polling update function, so the caller is responsible for this.
1339 */
1340static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1341{
1342 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01001343 int try;
Emeric Brun46591952012-05-18 15:47:34 +02001344
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001345 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001346 goto out_error;
1347
1348 if (conn->flags & CO_FL_HANDSHAKE)
1349 /* a handshake was requested */
1350 return 0;
1351
Willy Tarreauabf08d92014-01-14 11:31:27 +01001352 /* let's realign the buffer to optimize I/O */
1353 if (buffer_empty(buf))
Emeric Brun46591952012-05-18 15:47:34 +02001354 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02001355
1356 /* read the largest possible block. For this, we perform only one call
1357 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1358 * in which case we accept to do it once again. A new attempt is made on
1359 * EINTR too.
1360 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01001361 while (count > 0) {
Willy Tarreauabf08d92014-01-14 11:31:27 +01001362 /* first check if we have some room after p+i */
1363 try = buf->data + buf->size - (buf->p + buf->i);
1364 /* otherwise continue between data and p-o */
1365 if (try <= 0) {
1366 try = buf->p - (buf->data + buf->o);
1367 if (try <= 0)
1368 break;
1369 }
1370 if (try > count)
1371 try = count;
1372
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001373 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001374 if (conn->flags & CO_FL_ERROR) {
1375 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001376 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001377 }
Emeric Brun46591952012-05-18 15:47:34 +02001378 if (ret > 0) {
1379 buf->i += ret;
1380 done += ret;
1381 if (ret < try)
1382 break;
1383 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02001384 }
1385 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001386 ret = SSL_get_error(conn->xprt_ctx, ret);
1387 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001388 /* error on protocol or underlying transport */
1389 if ((ret != SSL_ERROR_SYSCALL)
1390 || (errno && (errno != EAGAIN)))
1391 conn->flags |= CO_FL_ERROR;
1392
Emeric Brun644cde02012-12-14 11:21:13 +01001393 /* Clear openssl global errors stack */
1394 ERR_clear_error();
1395 }
Emeric Brun46591952012-05-18 15:47:34 +02001396 goto read0;
1397 }
1398 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001399 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001400 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001401 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001402 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001403 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001404 break;
1405 }
1406 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001407 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1408 /* handshake is running, and it may need to re-enable read */
1409 conn->flags |= CO_FL_SSL_WAIT_HS;
1410 __conn_sock_want_recv(conn);
1411 break;
1412 }
Emeric Brun46591952012-05-18 15:47:34 +02001413 /* we need to poll for retry a read later */
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001414 fd_cant_recv(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001415 break;
1416 }
1417 /* otherwise it's a real error */
1418 goto out_error;
1419 }
1420 }
1421 return done;
1422
1423 read0:
1424 conn_sock_read0(conn);
1425 return done;
1426 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001427 /* Clear openssl global errors stack */
1428 ERR_clear_error();
1429
Emeric Brun46591952012-05-18 15:47:34 +02001430 conn->flags |= CO_FL_ERROR;
1431 return done;
1432}
1433
1434
1435/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1436 * <flags> may contain MSG_MORE to make the system hold on without sending
1437 * data too fast, but this flag is ignored at the moment.
1438 * Only one call to send() is performed, unless the buffer wraps, in which case
1439 * a second call may be performed. The connection's flags are updated with
1440 * whatever special event is detected (error, empty). The caller is responsible
1441 * for taking care of those events and avoiding the call if inappropriate. The
1442 * function does not call the connection's polling update function, so the caller
1443 * is responsible for this.
1444 */
1445static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1446{
1447 int ret, try, done;
1448
1449 done = 0;
1450
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001451 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001452 goto out_error;
1453
1454 if (conn->flags & CO_FL_HANDSHAKE)
1455 /* a handshake was requested */
1456 return 0;
1457
1458 /* send the largest possible block. For this we perform only one call
1459 * to send() unless the buffer wraps and we exactly fill the first hunk,
1460 * in which case we accept to do it once again.
1461 */
1462 while (buf->o) {
Kevin Hestercad82342013-05-30 15:12:41 -07001463 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01001464
1465 if (global.tune.ssl_max_record && try > global.tune.ssl_max_record)
1466 try = global.tune.ssl_max_record;
1467
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001468 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001469 if (conn->flags & CO_FL_ERROR) {
1470 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001471 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001472 }
Emeric Brun46591952012-05-18 15:47:34 +02001473 if (ret > 0) {
1474 buf->o -= ret;
1475 done += ret;
1476
Willy Tarreau5fb38032012-12-16 19:39:09 +01001477 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001478 /* optimize data alignment in the buffer */
1479 buf->p = buf->data;
1480
1481 /* if the system buffer is full, don't insist */
1482 if (ret < try)
1483 break;
1484 }
1485 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001486 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001487 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001488 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1489 /* handshake is running, and it may need to re-enable write */
1490 conn->flags |= CO_FL_SSL_WAIT_HS;
1491 __conn_sock_want_send(conn);
1492 break;
1493 }
Emeric Brun46591952012-05-18 15:47:34 +02001494 /* we need to poll to retry a write later */
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001495 fd_cant_send(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001496 break;
1497 }
1498 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001499 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001500 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001501 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001502 break;
1503 }
1504 goto out_error;
1505 }
1506 }
1507 return done;
1508
1509 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001510 /* Clear openssl global errors stack */
1511 ERR_clear_error();
1512
Emeric Brun46591952012-05-18 15:47:34 +02001513 conn->flags |= CO_FL_ERROR;
1514 return done;
1515}
1516
Emeric Brun46591952012-05-18 15:47:34 +02001517static void ssl_sock_close(struct connection *conn) {
1518
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001519 if (conn->xprt_ctx) {
1520 SSL_free(conn->xprt_ctx);
1521 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001522 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001523 }
Emeric Brun46591952012-05-18 15:47:34 +02001524}
1525
1526/* This function tries to perform a clean shutdown on an SSL connection, and in
1527 * any case, flags the connection as reusable if no handshake was in progress.
1528 */
1529static void ssl_sock_shutw(struct connection *conn, int clean)
1530{
1531 if (conn->flags & CO_FL_HANDSHAKE)
1532 return;
1533 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001534 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1535 /* Clear openssl global errors stack */
1536 ERR_clear_error();
1537 }
Emeric Brun46591952012-05-18 15:47:34 +02001538
1539 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001540 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001541}
1542
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001543/* used for logging, may be changed for a sample fetch later */
1544const char *ssl_sock_get_cipher_name(struct connection *conn)
1545{
1546 if (!conn->xprt && !conn->xprt_ctx)
1547 return NULL;
1548 return SSL_get_cipher_name(conn->xprt_ctx);
1549}
1550
1551/* used for logging, may be changed for a sample fetch later */
1552const char *ssl_sock_get_proto_version(struct connection *conn)
1553{
1554 if (!conn->xprt && !conn->xprt_ctx)
1555 return NULL;
1556 return SSL_get_version(conn->xprt_ctx);
1557}
1558
Willy Tarreau8d598402012-10-22 17:58:39 +02001559/* Extract a serial from a cert, and copy it to a chunk.
1560 * Returns 1 if serial is found and copied, 0 if no serial found and
1561 * -1 if output is not large enough.
1562 */
1563static int
1564ssl_sock_get_serial(X509 *crt, struct chunk *out)
1565{
1566 ASN1_INTEGER *serial;
1567
1568 serial = X509_get_serialNumber(crt);
1569 if (!serial)
1570 return 0;
1571
1572 if (out->size < serial->length)
1573 return -1;
1574
1575 memcpy(out->str, serial->data, serial->length);
1576 out->len = serial->length;
1577 return 1;
1578}
1579
Emeric Brunce5ad802012-10-22 14:11:22 +02001580
1581/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1582 * Returns 1 if serial is found and copied, 0 if no valid time found
1583 * and -1 if output is not large enough.
1584 */
1585static int
1586ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1587{
1588 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1589 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1590
1591 if (gentm->length < 12)
1592 return 0;
1593 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1594 return 0;
1595 if (out->size < gentm->length-2)
1596 return -1;
1597
1598 memcpy(out->str, gentm->data+2, gentm->length-2);
1599 out->len = gentm->length-2;
1600 return 1;
1601 }
1602 else if (tm->type == V_ASN1_UTCTIME) {
1603 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1604
1605 if (utctm->length < 10)
1606 return 0;
1607 if (utctm->data[0] >= 0x35)
1608 return 0;
1609 if (out->size < utctm->length)
1610 return -1;
1611
1612 memcpy(out->str, utctm->data, utctm->length);
1613 out->len = utctm->length;
1614 return 1;
1615 }
1616
1617 return 0;
1618}
1619
Emeric Brun87855892012-10-17 17:39:35 +02001620/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1621 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1622 */
1623static int
1624ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1625{
1626 X509_NAME_ENTRY *ne;
1627 int i, j, n;
1628 int cur = 0;
1629 const char *s;
1630 char tmp[128];
1631
1632 out->len = 0;
1633 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1634 if (pos < 0)
1635 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1636 else
1637 j = i;
1638
1639 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1640 n = OBJ_obj2nid(ne->object);
1641 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1642 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1643 s = tmp;
1644 }
1645
1646 if (chunk_strcasecmp(entry, s) != 0)
1647 continue;
1648
1649 if (pos < 0)
1650 cur--;
1651 else
1652 cur++;
1653
1654 if (cur != pos)
1655 continue;
1656
1657 if (ne->value->length > out->size)
1658 return -1;
1659
1660 memcpy(out->str, ne->value->data, ne->value->length);
1661 out->len = ne->value->length;
1662 return 1;
1663 }
1664
1665 return 0;
1666
1667}
1668
1669/* Extract and format full DN from a X509_NAME and copy result into a chunk
1670 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1671 */
1672static int
1673ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1674{
1675 X509_NAME_ENTRY *ne;
1676 int i, n, ln;
1677 int l = 0;
1678 const char *s;
1679 char *p;
1680 char tmp[128];
1681
1682 out->len = 0;
1683 p = out->str;
1684 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1685 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1686 n = OBJ_obj2nid(ne->object);
1687 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1688 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1689 s = tmp;
1690 }
1691 ln = strlen(s);
1692
1693 l += 1 + ln + 1 + ne->value->length;
1694 if (l > out->size)
1695 return -1;
1696 out->len = l;
1697
1698 *(p++)='/';
1699 memcpy(p, s, ln);
1700 p += ln;
1701 *(p++)='=';
1702 memcpy(p, ne->value->data, ne->value->length);
1703 p += ne->value->length;
1704 }
1705
1706 if (!out->len)
1707 return 0;
1708
1709 return 1;
1710}
1711
Willy Tarreau7875d092012-09-10 08:20:03 +02001712/***** Below are some sample fetching functions for ACL/patterns *****/
1713
Emeric Brune64aef12012-09-21 13:15:06 +02001714/* boolean, returns true if client cert was present */
1715static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001716smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001717 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brune64aef12012-09-21 13:15:06 +02001718{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001719 struct connection *conn;
1720
1721 if (!l4)
1722 return 0;
1723
1724 conn = objt_conn(l4->si[0].end);
1725 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001726 return 0;
1727
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001728 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001729 smp->flags |= SMP_F_MAY_CHANGE;
1730 return 0;
1731 }
1732
1733 smp->flags = 0;
1734 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001735 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001736
1737 return 1;
1738}
1739
Willy Tarreau8d598402012-10-22 17:58:39 +02001740/* bin, returns serial in a binary chunk */
1741static int
1742smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001743 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02001744{
1745 X509 *crt = NULL;
1746 int ret = 0;
1747 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001748 struct connection *conn;
1749
1750 if (!l4)
1751 return 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02001752
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001753 conn = objt_conn(l4->si[0].end);
1754 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001755 return 0;
1756
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001757 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001758 smp->flags |= SMP_F_MAY_CHANGE;
1759 return 0;
1760 }
1761
1762 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001763 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001764 if (!crt)
1765 goto out;
1766
Willy Tarreau47ca5452012-12-23 20:22:19 +01001767 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001768 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1769 goto out;
1770
1771 smp->data.str = *smp_trash;
1772 smp->type = SMP_T_BIN;
1773 ret = 1;
1774out:
1775 if (crt)
1776 X509_free(crt);
1777 return ret;
1778}
Emeric Brune64aef12012-09-21 13:15:06 +02001779
James Votha051b4a2013-05-14 20:37:59 +02001780/* bin, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk */
1781static int
1782smp_fetch_ssl_c_sha1(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001783 const struct arg *args, struct sample *smp, const char *kw)
James Votha051b4a2013-05-14 20:37:59 +02001784{
1785 X509 *crt = NULL;
1786 const EVP_MD *digest;
1787 int ret = 0;
1788 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001789 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02001790
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001791 if (!l4)
James Votha051b4a2013-05-14 20:37:59 +02001792 return 0;
1793
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001794 conn = objt_conn(l4->si[0].end);
1795 if (!conn || conn->xprt != &ssl_sock)
1796 return 0;
1797
1798 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02001799 smp->flags |= SMP_F_MAY_CHANGE;
1800 return 0;
1801 }
1802
1803 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001804 crt = SSL_get_peer_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02001805 if (!crt)
1806 goto out;
1807
1808 smp_trash = get_trash_chunk();
1809 digest = EVP_sha1();
1810 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
1811
1812 smp->data.str = *smp_trash;
1813 smp->type = SMP_T_BIN;
1814 ret = 1;
1815out:
1816 if (crt)
1817 X509_free(crt);
1818 return ret;
1819}
1820
Emeric Brunce5ad802012-10-22 14:11:22 +02001821/*str, returns notafter date in ASN1_UTCTIME format */
1822static int
1823smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001824 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001825{
1826 X509 *crt = NULL;
1827 int ret = 0;
1828 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001829 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02001830
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001831 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02001832 return 0;
1833
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001834 conn = objt_conn(l4->si[0].end);
1835 if (!conn || conn->xprt != &ssl_sock)
1836 return 0;
1837
1838 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001839 smp->flags |= SMP_F_MAY_CHANGE;
1840 return 0;
1841 }
1842
1843 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001844 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001845 if (!crt)
1846 goto out;
1847
Willy Tarreau47ca5452012-12-23 20:22:19 +01001848 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001849 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1850 goto out;
1851
1852 smp->data.str = *smp_trash;
1853 smp->type = SMP_T_STR;
1854 ret = 1;
1855out:
1856 if (crt)
1857 X509_free(crt);
1858 return ret;
1859}
1860
Emeric Brun87855892012-10-17 17:39:35 +02001861/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1862static int
1863smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001864 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02001865{
1866 X509 *crt = NULL;
1867 X509_NAME *name;
1868 int ret = 0;
1869 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001870 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02001871
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001872 if (!l4)
Emeric Brun87855892012-10-17 17:39:35 +02001873 return 0;
1874
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001875 conn = objt_conn(l4->si[0].end);
1876 if (!conn || conn->xprt != &ssl_sock)
1877 return 0;
1878
1879 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001880 smp->flags |= SMP_F_MAY_CHANGE;
1881 return 0;
1882 }
1883
1884 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001885 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001886 if (!crt)
1887 goto out;
1888
1889 name = X509_get_issuer_name(crt);
1890 if (!name)
1891 goto out;
1892
Willy Tarreau47ca5452012-12-23 20:22:19 +01001893 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001894 if (args && args[0].type == ARGT_STR) {
1895 int pos = 1;
1896
1897 if (args[1].type == ARGT_SINT)
1898 pos = args[1].data.sint;
1899 else if (args[1].type == ARGT_UINT)
1900 pos =(int)args[1].data.uint;
1901
1902 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1903 goto out;
1904 }
1905 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1906 goto out;
1907
1908 smp->type = SMP_T_STR;
1909 smp->data.str = *smp_trash;
1910 ret = 1;
1911out:
1912 if (crt)
1913 X509_free(crt);
1914 return ret;
1915}
1916
Emeric Brunce5ad802012-10-22 14:11:22 +02001917/*str, returns notbefore date in ASN1_UTCTIME format */
1918static int
1919smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001920 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001921{
1922 X509 *crt = NULL;
1923 int ret = 0;
1924 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001925 struct connection *conn;
1926
1927 if (!l4)
1928 return 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02001929
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001930 conn = objt_conn(l4->si[0].end);
1931 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001932 return 0;
1933
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001934 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001935 smp->flags |= SMP_F_MAY_CHANGE;
1936 return 0;
1937 }
1938
1939 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001940 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001941 if (!crt)
1942 goto out;
1943
Willy Tarreau47ca5452012-12-23 20:22:19 +01001944 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001945 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1946 goto out;
1947
1948 smp->data.str = *smp_trash;
1949 smp->type = SMP_T_STR;
1950 ret = 1;
1951out:
1952 if (crt)
1953 X509_free(crt);
1954 return ret;
1955}
1956
Emeric Brun87855892012-10-17 17:39:35 +02001957/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1958static int
1959smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001960 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02001961{
1962 X509 *crt = NULL;
1963 X509_NAME *name;
1964 int ret = 0;
1965 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001966 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02001967
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001968 if (!l4)
Emeric Brun87855892012-10-17 17:39:35 +02001969 return 0;
1970
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001971 conn = objt_conn(l4->si[0].end);
1972 if (!conn || conn->xprt != &ssl_sock)
1973 return 0;
1974
1975 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001976 smp->flags |= SMP_F_MAY_CHANGE;
1977 return 0;
1978 }
1979
1980 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001981 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001982 if (!crt)
1983 goto out;
1984
1985 name = X509_get_subject_name(crt);
1986 if (!name)
1987 goto out;
1988
Willy Tarreau47ca5452012-12-23 20:22:19 +01001989 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001990 if (args && args[0].type == ARGT_STR) {
1991 int pos = 1;
1992
1993 if (args[1].type == ARGT_SINT)
1994 pos = args[1].data.sint;
1995 else if (args[1].type == ARGT_UINT)
1996 pos =(int)args[1].data.uint;
1997
1998 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1999 goto out;
2000 }
2001 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2002 goto out;
2003
2004 smp->type = SMP_T_STR;
2005 smp->data.str = *smp_trash;
2006 ret = 1;
2007out:
2008 if (crt)
2009 X509_free(crt);
2010 return ret;
2011}
Emeric Brun9143d372012-12-20 15:44:16 +01002012
2013/* integer, returns true if current session use a client certificate */
2014static int
2015smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002016 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun9143d372012-12-20 15:44:16 +01002017{
2018 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002019 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01002020
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002021 if (!l4)
Emeric Brun9143d372012-12-20 15:44:16 +01002022 return 0;
2023
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002024 conn = objt_conn(l4->si[0].end);
2025 if (!conn || conn->xprt != &ssl_sock)
2026 return 0;
2027
2028 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01002029 smp->flags |= SMP_F_MAY_CHANGE;
2030 return 0;
2031 }
2032
2033 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002034 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01002035 if (crt) {
2036 X509_free(crt);
2037 }
2038
2039 smp->type = SMP_T_BOOL;
2040 smp->data.uint = (crt != NULL);
2041 return 1;
2042}
2043
Emeric Bruna7359fd2012-10-17 15:03:11 +02002044/* integer, returns the client certificate version */
2045static int
2046smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002047 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002048{
2049 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002050 struct connection *conn;
2051
2052 if (!l4)
2053 return 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02002054
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002055 conn = objt_conn(l4->si[0].end);
2056 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002057 return 0;
2058
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002059 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002060 smp->flags |= SMP_F_MAY_CHANGE;
2061 return 0;
2062 }
2063
2064 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002065 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002066 if (!crt)
2067 return 0;
2068
2069 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2070 X509_free(crt);
2071 smp->type = SMP_T_UINT;
2072
2073 return 1;
2074}
2075
Emeric Brun7f56e742012-10-19 18:15:40 +02002076/* str, returns the client certificate sig alg */
2077static int
2078smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002079 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002080{
2081 X509 *crt;
2082 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002083 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02002084
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002085 if (!l4)
Emeric Brun7f56e742012-10-19 18:15:40 +02002086 return 0;
2087
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002088 conn = objt_conn(l4->si[0].end);
2089 if (!conn || conn->xprt != &ssl_sock)
2090 return 0;
2091
2092 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002093 smp->flags |= SMP_F_MAY_CHANGE;
2094 return 0;
2095 }
2096
2097 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002098 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002099 if (!crt)
2100 return 0;
2101
2102 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2103
2104 smp->data.str.str = (char *)OBJ_nid2sn(nid);
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002105 if (!smp->data.str.str) {
2106 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02002107 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002108 }
Emeric Brun7f56e742012-10-19 18:15:40 +02002109
2110 smp->type = SMP_T_CSTR;
2111 smp->data.str.len = strlen(smp->data.str.str);
2112 X509_free(crt);
2113
2114 return 1;
2115}
2116
Emeric Brun521a0112012-10-22 12:22:55 +02002117/* str, returns the client certificate key alg */
2118static int
2119smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002120 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002121{
2122 X509 *crt;
2123 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002124 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02002125
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002126 if (!l4)
Emeric Brun521a0112012-10-22 12:22:55 +02002127 return 0;
2128
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002129 conn = objt_conn(l4->si[0].end);
2130 if (!conn || conn->xprt != &ssl_sock)
2131 return 0;
2132
2133 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002134 smp->flags |= SMP_F_MAY_CHANGE;
2135 return 0;
2136 }
2137
2138 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002139 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002140 if (!crt)
2141 return 0;
2142
2143 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2144
2145 smp->data.str.str = (char *)OBJ_nid2sn(nid);
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002146 if (!smp->data.str.str) {
2147 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02002148 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002149 }
Emeric Brun521a0112012-10-22 12:22:55 +02002150
2151 smp->type = SMP_T_CSTR;
2152 smp->data.str.len = strlen(smp->data.str.str);
2153 X509_free(crt);
2154
2155 return 1;
2156}
2157
Emeric Brun2525b6b2012-10-18 15:59:43 +02002158/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02002159static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002160smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002161 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002162{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002163 struct connection *conn = objt_conn(l4->si[0].end);
2164
Willy Tarreau7875d092012-09-10 08:20:03 +02002165 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002166 smp->data.uint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02002167 return 1;
2168}
2169
Emeric Brun2525b6b2012-10-18 15:59:43 +02002170/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02002171static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002172smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002173 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002174{
2175#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002176 struct connection *conn = objt_conn(l4->si[0].end);
2177
Willy Tarreau7875d092012-09-10 08:20:03 +02002178 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002179 smp->data.uint = (conn && conn->xprt == &ssl_sock) &&
2180 conn->xprt_ctx &&
2181 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02002182 return 1;
2183#else
2184 return 0;
2185#endif
2186}
2187
Willy Tarreau8d598402012-10-22 17:58:39 +02002188/* bin, returns serial in a binary chunk */
2189static int
2190smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002191 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02002192{
2193 X509 *crt = NULL;
2194 int ret = 0;
2195 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002196 struct connection *conn;
2197
2198 if (!l4)
2199 return 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02002200
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002201 conn = objt_conn(l4->si[0].end);
2202 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02002203 return 0;
2204
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002205 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02002206 smp->flags |= SMP_F_MAY_CHANGE;
2207 return 0;
2208 }
2209
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002210 crt = SSL_get_certificate(conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02002211 if (!crt)
2212 goto out;
2213
Willy Tarreau47ca5452012-12-23 20:22:19 +01002214 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02002215 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
2216 goto out;
2217
2218 smp->data.str = *smp_trash;
2219 smp->type = SMP_T_BIN;
2220 ret = 1;
2221out:
2222 return ret;
2223}
Emeric Brunce5ad802012-10-22 14:11:22 +02002224/*str, returns notafter date in ASN1_UTCTIME format */
2225static int
2226smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002227 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002228{
2229 X509 *crt = NULL;
2230 int ret = 0;
2231 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002232 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02002233
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002234 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02002235 return 0;
2236
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002237 conn = objt_conn(l4->si[0].end);
2238 if (!conn || conn->xprt != &ssl_sock)
2239 return 0;
2240
2241 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002242 smp->flags |= SMP_F_MAY_CHANGE;
2243 return 0;
2244 }
2245
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002246 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002247 if (!crt)
2248 goto out;
2249
Willy Tarreau47ca5452012-12-23 20:22:19 +01002250 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002251 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
2252 goto out;
2253
2254 smp->data.str = *smp_trash;
2255 smp->type = SMP_T_STR;
2256 ret = 1;
2257out:
2258 return ret;
2259}
2260
2261/*str, returns notbefore date in ASN1_UTCTIME format */
2262static int
2263smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002264 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002265{
2266 X509 *crt = NULL;
2267 int ret = 0;
2268 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002269 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02002270
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002271 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02002272 return 0;
2273
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002274 conn = objt_conn(l4->si[0].end);
2275 if (!conn || conn->xprt != &ssl_sock)
2276 return 0;
2277
2278 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002279 smp->flags |= SMP_F_MAY_CHANGE;
2280 return 0;
2281 }
2282
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002283 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002284 if (!crt)
2285 goto out;
2286
Willy Tarreau47ca5452012-12-23 20:22:19 +01002287 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002288 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
2289 goto out;
2290
2291 smp->data.str = *smp_trash;
2292 smp->type = SMP_T_STR;
2293 ret = 1;
2294out:
2295 return ret;
2296}
Willy Tarreau8d598402012-10-22 17:58:39 +02002297
Emeric Bruna7359fd2012-10-17 15:03:11 +02002298/* integer, returns the frontend certificate version */
2299static int
2300smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002301 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002302{
2303 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002304 struct connection *conn;
Emeric Bruna7359fd2012-10-17 15:03:11 +02002305
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002306 if (!l4)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002307 return 0;
2308
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002309 conn = objt_conn(l4->si[0].end);
2310 if (!conn || conn->xprt != &ssl_sock)
2311 return 0;
2312
2313 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002314 smp->flags |= SMP_F_MAY_CHANGE;
2315 return 0;
2316 }
2317
2318 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002319 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002320 if (!crt)
2321 return 0;
2322
2323 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2324 smp->type = SMP_T_UINT;
2325
2326 return 1;
2327}
2328
Emeric Brun7f56e742012-10-19 18:15:40 +02002329/* str, returns the client certificate sig alg */
2330static int
2331smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002332 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002333{
2334 X509 *crt;
2335 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002336 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02002337
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002338 if (!l4)
Emeric Brun7f56e742012-10-19 18:15:40 +02002339 return 0;
2340
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002341 conn = objt_conn(l4->si[0].end);
2342 if (!conn || conn->xprt != &ssl_sock)
2343 return 0;
2344
2345 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002346 smp->flags |= SMP_F_MAY_CHANGE;
2347 return 0;
2348 }
2349
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002350 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002351 if (!crt)
2352 return 0;
2353
2354 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2355
2356 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2357 if (!smp->data.str.str)
2358 return 0;
2359
2360 smp->type = SMP_T_CSTR;
2361 smp->data.str.len = strlen(smp->data.str.str);
2362
2363 return 1;
2364}
2365
Emeric Brun521a0112012-10-22 12:22:55 +02002366/* str, returns the client certificate key alg */
2367static int
2368smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002369 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002370{
2371 X509 *crt;
2372 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002373 struct connection *conn;
2374
2375 if (!l4)
2376 return 0;
Emeric Brun521a0112012-10-22 12:22:55 +02002377
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002378 conn = objt_conn(l4->si[0].end);
2379 if (!conn || conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002380 return 0;
2381
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002382 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002383 smp->flags |= SMP_F_MAY_CHANGE;
2384 return 0;
2385 }
2386
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002387 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002388 if (!crt)
2389 return 0;
2390
2391 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2392
2393 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2394 if (!smp->data.str.str)
2395 return 0;
2396
2397 smp->type = SMP_T_CSTR;
2398 smp->data.str.len = strlen(smp->data.str.str);
2399
2400 return 1;
2401}
2402
Emeric Brun87855892012-10-17 17:39:35 +02002403/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2404static int
2405smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002406 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002407{
2408 X509 *crt = NULL;
2409 X509_NAME *name;
2410 int ret = 0;
2411 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002412 struct connection *conn;
2413
2414 if (!l4)
2415 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02002416
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002417 conn = objt_conn(l4->si[0].end);
2418 if (!conn || conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002419 return 0;
2420
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002421 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002422 smp->flags |= SMP_F_MAY_CHANGE;
2423 return 0;
2424 }
2425
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002426 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002427 if (!crt)
2428 goto out;
2429
2430 name = X509_get_issuer_name(crt);
2431 if (!name)
2432 goto out;
2433
Willy Tarreau47ca5452012-12-23 20:22:19 +01002434 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002435 if (args && args[0].type == ARGT_STR) {
2436 int pos = 1;
2437
2438 if (args[1].type == ARGT_SINT)
2439 pos = args[1].data.sint;
2440 else if (args[1].type == ARGT_UINT)
2441 pos =(int)args[1].data.uint;
2442
2443 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2444 goto out;
2445 }
2446 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2447 goto out;
2448
2449 smp->type = SMP_T_STR;
2450 smp->data.str = *smp_trash;
2451 ret = 1;
2452out:
2453 return ret;
2454}
2455
2456/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2457static int
2458smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002459 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002460{
2461 X509 *crt = NULL;
2462 X509_NAME *name;
2463 int ret = 0;
2464 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002465 struct connection *conn;
2466
2467 if (!l4)
2468 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02002469
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002470 conn = objt_conn(l4->si[0].end);
2471 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002472 return 0;
2473
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002474 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002475 smp->flags |= SMP_F_MAY_CHANGE;
2476 return 0;
2477 }
2478
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002479 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002480 if (!crt)
2481 goto out;
2482
2483 name = X509_get_subject_name(crt);
2484 if (!name)
2485 goto out;
2486
Willy Tarreau47ca5452012-12-23 20:22:19 +01002487 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002488 if (args && args[0].type == ARGT_STR) {
2489 int pos = 1;
2490
2491 if (args[1].type == ARGT_SINT)
2492 pos = args[1].data.sint;
2493 else if (args[1].type == ARGT_UINT)
2494 pos =(int)args[1].data.uint;
2495
2496 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2497 goto out;
2498 }
2499 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2500 goto out;
2501
2502 smp->type = SMP_T_STR;
2503 smp->data.str = *smp_trash;
2504 ret = 1;
2505out:
2506 return ret;
2507}
2508
Emeric Brun589fcad2012-10-16 14:13:26 +02002509static int
2510smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002511 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002512{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002513 struct connection *conn;
2514
Emeric Brun589fcad2012-10-16 14:13:26 +02002515 smp->flags = 0;
2516
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002517 if (!l4)
2518 return 0;
2519
2520 conn = objt_conn(l4->si[0].end);
2521 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002522 return 0;
2523
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002524 smp->data.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002525 if (!smp->data.str.str)
2526 return 0;
2527
2528 smp->type = SMP_T_CSTR;
2529 smp->data.str.len = strlen(smp->data.str.str);
2530
2531 return 1;
2532}
2533
2534static int
2535smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002536 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002537{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002538 struct connection *conn;
2539
Emeric Brun589fcad2012-10-16 14:13:26 +02002540 smp->flags = 0;
2541
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002542 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002543 return 0;
2544
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002545 conn = objt_conn(l4->si[0].end);
2546 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002547 return 0;
2548
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002549 if (!SSL_get_cipher_bits(conn->xprt_ctx, (int *)&smp->data.uint))
2550 return 0;
2551
Emeric Brun589fcad2012-10-16 14:13:26 +02002552 smp->type = SMP_T_UINT;
2553
2554 return 1;
2555}
2556
2557static int
2558smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002559 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002560{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002561 struct connection *conn;
2562
Emeric Brun589fcad2012-10-16 14:13:26 +02002563 smp->flags = 0;
2564
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002565 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002566 return 0;
2567
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002568 conn = objt_conn(l4->si[0].end);
2569 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2570 return 0;
2571
2572 smp->data.uint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002573 if (!smp->data.uint)
2574 return 0;
2575
2576 smp->type = SMP_T_UINT;
2577
2578 return 1;
2579}
2580
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002581#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002582static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002583smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002584 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002585{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002586 struct connection *conn;
2587
Willy Tarreaua33c6542012-10-15 13:19:06 +02002588 smp->flags = 0;
2589 smp->type = SMP_T_CSTR;
2590
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002591 if (!l4)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002592 return 0;
2593
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002594 conn = objt_conn(l4->si[0].end);
2595 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2596 return 0;
2597
Willy Tarreaua33c6542012-10-15 13:19:06 +02002598 smp->data.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002599 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002600 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2601
2602 if (!smp->data.str.str)
2603 return 0;
2604
2605 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002606}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002607#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002608
Willy Tarreauab861d32013-04-02 02:30:41 +02002609#ifdef OPENSSL_ALPN_NEGOTIATED
2610static int
2611smp_fetch_ssl_fc_alpn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002612 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreauab861d32013-04-02 02:30:41 +02002613{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002614 struct connection *conn;
2615
Willy Tarreauab861d32013-04-02 02:30:41 +02002616 smp->flags = 0;
2617 smp->type = SMP_T_CSTR;
2618
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002619 if (!l4)
2620 return 0;
2621
2622 conn = objt_conn(l4->si[0].end);
2623 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02002624 return 0;
2625
2626 smp->data.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002627 SSL_get0_alpn_negotiated(conn->xprt_ctx,
Willy Tarreauab861d32013-04-02 02:30:41 +02002628 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2629
2630 if (!smp->data.str.str)
2631 return 0;
2632
2633 return 1;
2634}
2635#endif
2636
Willy Tarreaua33c6542012-10-15 13:19:06 +02002637static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002638smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002639 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002640{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002641 struct connection *conn;
2642
Emeric Brun589fcad2012-10-16 14:13:26 +02002643 smp->flags = 0;
2644
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002645 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002646 return 0;
2647
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002648 conn = objt_conn(l4->si[0].end);
2649 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2650 return 0;
2651
2652 smp->data.str.str = (char *)SSL_get_version(conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002653 if (!smp->data.str.str)
2654 return 0;
2655
2656 smp->type = SMP_T_CSTR;
2657 smp->data.str.len = strlen(smp->data.str.str);
2658
2659 return 1;
2660}
2661
2662static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002663smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002664 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunfe68f682012-10-16 14:59:28 +02002665{
2666#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2667 SSL_SESSION *sess;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002668 struct connection *conn;
Emeric Brunfe68f682012-10-16 14:59:28 +02002669
2670 smp->flags = 0;
2671 smp->type = SMP_T_CBIN;
2672
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002673 if (!l4)
Emeric Brunfe68f682012-10-16 14:59:28 +02002674 return 0;
2675
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002676 conn = objt_conn(l4->si[0].end);
2677 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2678 return 0;
2679
2680 sess = SSL_get_session(conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002681 if (!sess)
2682 return 0;
2683
2684 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2685 if (!smp->data.str.str || !&smp->data.str.len)
2686 return 0;
2687
2688 return 1;
2689#else
2690 return 0;
2691#endif
2692}
2693
2694static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002695smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002696 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002697{
2698#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002699 struct connection *conn;
2700
Willy Tarreau7875d092012-09-10 08:20:03 +02002701 smp->flags = 0;
2702 smp->type = SMP_T_CSTR;
2703
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002704 if (!l4)
Willy Tarreau7875d092012-09-10 08:20:03 +02002705 return 0;
2706
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002707 conn = objt_conn(l4->si[0].end);
2708 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2709 return 0;
2710
2711 smp->data.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau3e394c92012-09-14 23:56:58 +02002712 if (!smp->data.str.str)
2713 return 0;
2714
Willy Tarreau7875d092012-09-10 08:20:03 +02002715 smp->data.str.len = strlen(smp->data.str.str);
2716 return 1;
2717#else
2718 return 0;
2719#endif
2720}
2721
Emeric Brun2525b6b2012-10-18 15:59:43 +02002722/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002723static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002724smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002725 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002726{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002727 struct connection *conn;
2728
2729 if (!l4)
Emeric Brunf282a812012-09-21 15:27:54 +02002730 return 0;
2731
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002732 conn = objt_conn(l4->si[0].end);
2733 if (!conn || conn->xprt != &ssl_sock)
2734 return 0;
2735
2736 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002737 smp->flags = SMP_F_MAY_CHANGE;
2738 return 0;
2739 }
2740
2741 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002742 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002743 smp->flags = 0;
2744
2745 return 1;
2746}
2747
Emeric Brun2525b6b2012-10-18 15:59:43 +02002748/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002749static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002750smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002751 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002752{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002753 struct connection *conn;
2754
2755 if (!l4)
2756 return 0;
2757
2758 conn = objt_conn(l4->si[0].end);
2759 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002760 return 0;
2761
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002762 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002763 smp->flags = SMP_F_MAY_CHANGE;
2764 return 0;
2765 }
2766
2767 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002768 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002769 smp->flags = 0;
2770
2771 return 1;
2772}
2773
Emeric Brun2525b6b2012-10-18 15:59:43 +02002774/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002775static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002776smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002777 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002778{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002779 struct connection *conn;
2780
2781 if (!l4)
Emeric Brunf282a812012-09-21 15:27:54 +02002782 return 0;
2783
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002784 conn = objt_conn(l4->si[0].end);
2785 if (!conn || conn->xprt != &ssl_sock)
2786 return 0;
2787
2788 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002789 smp->flags = SMP_F_MAY_CHANGE;
2790 return 0;
2791 }
2792
2793 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002794 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002795 smp->flags = 0;
2796
2797 return 1;
2798}
2799
Emeric Brun2525b6b2012-10-18 15:59:43 +02002800/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002801static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002802smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002803 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002804{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002805 struct connection *conn;
2806
2807 if (!l4)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002808 return 0;
2809
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002810 conn = objt_conn(l4->si[0].end);
2811 if (!conn || conn->xprt != &ssl_sock)
2812 return 0;
2813
2814 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002815 smp->flags = SMP_F_MAY_CHANGE;
2816 return 0;
2817 }
2818
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002819 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002820 return 0;
2821
2822 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002823 smp->data.uint = (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002824 smp->flags = 0;
2825
2826 return 1;
2827}
2828
Emeric Brunfb510ea2012-10-05 12:00:26 +02002829/* parse the "ca-file" bind keyword */
2830static 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 +02002831{
2832 if (!*args[cur_arg + 1]) {
2833 if (err)
2834 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2835 return ERR_ALERT | ERR_FATAL;
2836 }
2837
Emeric Brunef42d922012-10-11 16:11:36 +02002838 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2839 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2840 else
2841 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002842
Emeric Brund94b3fe2012-09-20 18:23:56 +02002843 return 0;
2844}
2845
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002846/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002847static 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 +02002848{
2849 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002850 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002851 return ERR_ALERT | ERR_FATAL;
2852 }
2853
Emeric Brun76d88952012-10-05 15:47:31 +02002854 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002855 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002856 return 0;
2857}
2858
2859/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002860static 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 +02002861{
Willy Tarreau38011032013-08-13 16:59:39 +02002862 char path[MAXPATHLEN];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002863 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002864 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002865 return ERR_ALERT | ERR_FATAL;
2866 }
2867
Emeric Brunc8e8d122012-10-02 18:42:10 +02002868 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
Willy Tarreau38011032013-08-13 16:59:39 +02002869 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02002870 memprintf(err, "'%s' : path too long", args[cur_arg]);
2871 return ERR_ALERT | ERR_FATAL;
2872 }
2873 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2874 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2875 return ERR_ALERT | ERR_FATAL;
2876
2877 return 0;
2878 }
2879
Willy Tarreau4348fad2012-09-20 16:48:07 +02002880 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002881 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002882
2883 return 0;
2884}
2885
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002886/* parse the "crt-list" bind keyword */
2887static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2888{
2889 if (!*args[cur_arg + 1]) {
2890 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
2891 return ERR_ALERT | ERR_FATAL;
2892 }
2893
Willy Tarreauad1731d2013-04-02 17:35:58 +02002894 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
2895 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002896 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02002897 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002898
2899 return 0;
2900}
2901
Emeric Brunfb510ea2012-10-05 12:00:26 +02002902/* parse the "crl-file" bind keyword */
2903static 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 +02002904{
Emeric Brun051cdab2012-10-02 19:25:50 +02002905#ifndef X509_V_FLAG_CRL_CHECK
2906 if (err)
2907 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2908 return ERR_ALERT | ERR_FATAL;
2909#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002910 if (!*args[cur_arg + 1]) {
2911 if (err)
2912 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2913 return ERR_ALERT | ERR_FATAL;
2914 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002915
Emeric Brunef42d922012-10-11 16:11:36 +02002916 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2917 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2918 else
2919 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002920
Emeric Brun2b58d042012-09-20 17:10:03 +02002921 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002922#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002923}
2924
2925/* parse the "ecdhe" bind keyword keywords */
2926static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2927{
2928#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2929 if (err)
2930 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2931 return ERR_ALERT | ERR_FATAL;
2932#elif defined(OPENSSL_NO_ECDH)
2933 if (err)
2934 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2935 return ERR_ALERT | ERR_FATAL;
2936#else
2937 if (!*args[cur_arg + 1]) {
2938 if (err)
2939 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2940 return ERR_ALERT | ERR_FATAL;
2941 }
2942
2943 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002944
2945 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002946#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002947}
2948
Emeric Brun81c00f02012-09-21 14:31:21 +02002949/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2950static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2951{
2952 int code;
2953 char *p = args[cur_arg + 1];
2954 unsigned long long *ignerr = &conf->crt_ignerr;
2955
2956 if (!*p) {
2957 if (err)
2958 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2959 return ERR_ALERT | ERR_FATAL;
2960 }
2961
2962 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2963 ignerr = &conf->ca_ignerr;
2964
2965 if (strcmp(p, "all") == 0) {
2966 *ignerr = ~0ULL;
2967 return 0;
2968 }
2969
2970 while (p) {
2971 code = atoi(p);
2972 if ((code <= 0) || (code > 63)) {
2973 if (err)
2974 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2975 args[cur_arg], code, args[cur_arg + 1]);
2976 return ERR_ALERT | ERR_FATAL;
2977 }
2978 *ignerr |= 1ULL << code;
2979 p = strchr(p, ',');
2980 if (p)
2981 p++;
2982 }
2983
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002984 return 0;
2985}
2986
2987/* parse the "force-sslv3" bind keyword */
2988static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2989{
2990 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2991 return 0;
2992}
2993
2994/* parse the "force-tlsv10" bind keyword */
2995static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2996{
2997 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002998 return 0;
2999}
3000
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003001/* parse the "force-tlsv11" bind keyword */
3002static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3003{
3004#if SSL_OP_NO_TLSv1_1
3005 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
3006 return 0;
3007#else
3008 if (err)
3009 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
3010 return ERR_ALERT | ERR_FATAL;
3011#endif
3012}
3013
3014/* parse the "force-tlsv12" bind keyword */
3015static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3016{
3017#if SSL_OP_NO_TLSv1_2
3018 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
3019 return 0;
3020#else
3021 if (err)
3022 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
3023 return ERR_ALERT | ERR_FATAL;
3024#endif
3025}
3026
3027
Emeric Brun2d0c4822012-10-02 13:45:20 +02003028/* parse the "no-tls-tickets" bind keyword */
3029static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3030{
Emeric Brun89675492012-10-05 13:48:26 +02003031 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02003032 return 0;
3033}
3034
Emeric Brun2d0c4822012-10-02 13:45:20 +02003035
Emeric Brun9b3009b2012-10-05 11:55:06 +02003036/* parse the "no-sslv3" bind keyword */
3037static 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 +02003038{
Emeric Brun89675492012-10-05 13:48:26 +02003039 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003040 return 0;
3041}
3042
Emeric Brun9b3009b2012-10-05 11:55:06 +02003043/* parse the "no-tlsv10" bind keyword */
3044static 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 +02003045{
Emeric Brun89675492012-10-05 13:48:26 +02003046 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02003047 return 0;
3048}
3049
Emeric Brun9b3009b2012-10-05 11:55:06 +02003050/* parse the "no-tlsv11" bind keyword */
3051static 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 +02003052{
Emeric Brun89675492012-10-05 13:48:26 +02003053 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02003054 return 0;
3055}
3056
Emeric Brun9b3009b2012-10-05 11:55:06 +02003057/* parse the "no-tlsv12" bind keyword */
3058static 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 +02003059{
Emeric Brun89675492012-10-05 13:48:26 +02003060 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003061 return 0;
3062}
3063
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003064/* parse the "npn" bind keyword */
3065static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3066{
3067#ifdef OPENSSL_NPN_NEGOTIATED
3068 char *p1, *p2;
3069
3070 if (!*args[cur_arg + 1]) {
3071 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
3072 return ERR_ALERT | ERR_FATAL;
3073 }
3074
3075 free(conf->npn_str);
3076
3077 /* the NPN string is built as a suite of (<len> <name>)* */
3078 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
3079 conf->npn_str = calloc(1, conf->npn_len);
3080 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
3081
3082 /* replace commas with the name length */
3083 p1 = conf->npn_str;
3084 p2 = p1 + 1;
3085 while (1) {
3086 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
3087 if (!p2)
3088 p2 = p1 + 1 + strlen(p1 + 1);
3089
3090 if (p2 - (p1 + 1) > 255) {
3091 *p2 = '\0';
3092 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
3093 return ERR_ALERT | ERR_FATAL;
3094 }
3095
3096 *p1 = p2 - (p1 + 1);
3097 p1 = p2;
3098
3099 if (!*p2)
3100 break;
3101
3102 *(p2++) = '\0';
3103 }
3104 return 0;
3105#else
3106 if (err)
3107 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
3108 return ERR_ALERT | ERR_FATAL;
3109#endif
3110}
3111
Willy Tarreauab861d32013-04-02 02:30:41 +02003112/* parse the "alpn" bind keyword */
3113static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3114{
3115#ifdef OPENSSL_ALPN_NEGOTIATED
3116 char *p1, *p2;
3117
3118 if (!*args[cur_arg + 1]) {
3119 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
3120 return ERR_ALERT | ERR_FATAL;
3121 }
3122
3123 free(conf->alpn_str);
3124
3125 /* the ALPN string is built as a suite of (<len> <name>)* */
3126 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
3127 conf->alpn_str = calloc(1, conf->alpn_len);
3128 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
3129
3130 /* replace commas with the name length */
3131 p1 = conf->alpn_str;
3132 p2 = p1 + 1;
3133 while (1) {
3134 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
3135 if (!p2)
3136 p2 = p1 + 1 + strlen(p1 + 1);
3137
3138 if (p2 - (p1 + 1) > 255) {
3139 *p2 = '\0';
3140 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
3141 return ERR_ALERT | ERR_FATAL;
3142 }
3143
3144 *p1 = p2 - (p1 + 1);
3145 p1 = p2;
3146
3147 if (!*p2)
3148 break;
3149
3150 *(p2++) = '\0';
3151 }
3152 return 0;
3153#else
3154 if (err)
3155 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
3156 return ERR_ALERT | ERR_FATAL;
3157#endif
3158}
3159
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003160/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003161static 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 +02003162{
Willy Tarreau81796be2012-09-22 19:11:47 +02003163 struct listener *l;
3164
Willy Tarreau4348fad2012-09-20 16:48:07 +02003165 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02003166
3167 if (global.listen_default_ciphers && !conf->ciphers)
3168 conf->ciphers = strdup(global.listen_default_ciphers);
3169
Willy Tarreau81796be2012-09-22 19:11:47 +02003170 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003171 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02003172
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003173 return 0;
3174}
3175
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003176/* parse the "strict-sni" bind keyword */
3177static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3178{
3179 conf->strict_sni = 1;
3180 return 0;
3181}
3182
Emeric Brund94b3fe2012-09-20 18:23:56 +02003183/* parse the "verify" bind keyword */
3184static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3185{
3186 if (!*args[cur_arg + 1]) {
3187 if (err)
3188 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
3189 return ERR_ALERT | ERR_FATAL;
3190 }
3191
3192 if (strcmp(args[cur_arg + 1], "none") == 0)
3193 conf->verify = SSL_VERIFY_NONE;
3194 else if (strcmp(args[cur_arg + 1], "optional") == 0)
3195 conf->verify = SSL_VERIFY_PEER;
3196 else if (strcmp(args[cur_arg + 1], "required") == 0)
3197 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
3198 else {
3199 if (err)
3200 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
3201 args[cur_arg], args[cur_arg + 1]);
3202 return ERR_ALERT | ERR_FATAL;
3203 }
3204
3205 return 0;
3206}
3207
Willy Tarreau92faadf2012-10-10 23:04:25 +02003208/************** "server" keywords ****************/
3209
Emeric Brunef42d922012-10-11 16:11:36 +02003210/* parse the "ca-file" server keyword */
3211static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3212{
3213 if (!*args[*cur_arg + 1]) {
3214 if (err)
3215 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
3216 return ERR_ALERT | ERR_FATAL;
3217 }
3218
3219 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3220 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3221 else
3222 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
3223
3224 return 0;
3225}
3226
Willy Tarreau92faadf2012-10-10 23:04:25 +02003227/* parse the "check-ssl" server keyword */
3228static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3229{
3230 newsrv->check.use_ssl = 1;
3231 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3232 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3233 return 0;
3234}
3235
3236/* parse the "ciphers" server keyword */
3237static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3238{
3239 if (!*args[*cur_arg + 1]) {
3240 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
3241 return ERR_ALERT | ERR_FATAL;
3242 }
3243
3244 free(newsrv->ssl_ctx.ciphers);
3245 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
3246 return 0;
3247}
3248
Emeric Brunef42d922012-10-11 16:11:36 +02003249/* parse the "crl-file" server keyword */
3250static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3251{
3252#ifndef X509_V_FLAG_CRL_CHECK
3253 if (err)
3254 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
3255 return ERR_ALERT | ERR_FATAL;
3256#else
3257 if (!*args[*cur_arg + 1]) {
3258 if (err)
3259 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
3260 return ERR_ALERT | ERR_FATAL;
3261 }
3262
3263 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3264 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3265 else
3266 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
3267
3268 return 0;
3269#endif
3270}
3271
Emeric Bruna7aa3092012-10-26 12:58:00 +02003272/* parse the "crt" server keyword */
3273static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3274{
3275 if (!*args[*cur_arg + 1]) {
3276 if (err)
3277 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
3278 return ERR_ALERT | ERR_FATAL;
3279 }
3280
3281 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
3282 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3283 else
3284 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
3285
3286 return 0;
3287}
Emeric Brunef42d922012-10-11 16:11:36 +02003288
Willy Tarreau92faadf2012-10-10 23:04:25 +02003289/* parse the "force-sslv3" server keyword */
3290static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3291{
3292 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
3293 return 0;
3294}
3295
3296/* parse the "force-tlsv10" server keyword */
3297static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3298{
3299 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
3300 return 0;
3301}
3302
3303/* parse the "force-tlsv11" server keyword */
3304static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3305{
3306#if SSL_OP_NO_TLSv1_1
3307 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
3308 return 0;
3309#else
3310 if (err)
3311 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
3312 return ERR_ALERT | ERR_FATAL;
3313#endif
3314}
3315
3316/* parse the "force-tlsv12" server keyword */
3317static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3318{
3319#if SSL_OP_NO_TLSv1_2
3320 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
3321 return 0;
3322#else
3323 if (err)
3324 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
3325 return ERR_ALERT | ERR_FATAL;
3326#endif
3327}
3328
3329/* parse the "no-sslv3" server keyword */
3330static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3331{
3332 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
3333 return 0;
3334}
3335
3336/* parse the "no-tlsv10" server keyword */
3337static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3338{
3339 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
3340 return 0;
3341}
3342
3343/* parse the "no-tlsv11" server keyword */
3344static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3345{
3346 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
3347 return 0;
3348}
3349
3350/* parse the "no-tlsv12" server keyword */
3351static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3352{
3353 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
3354 return 0;
3355}
3356
Emeric Brunf9c5c472012-10-11 15:28:34 +02003357/* parse the "no-tls-tickets" server keyword */
3358static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3359{
3360 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
3361 return 0;
3362}
3363
Willy Tarreau92faadf2012-10-10 23:04:25 +02003364/* parse the "ssl" server keyword */
3365static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3366{
3367 newsrv->use_ssl = 1;
3368 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3369 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3370 return 0;
3371}
3372
Emeric Brunef42d922012-10-11 16:11:36 +02003373/* parse the "verify" server keyword */
3374static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3375{
3376 if (!*args[*cur_arg + 1]) {
3377 if (err)
3378 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
3379 return ERR_ALERT | ERR_FATAL;
3380 }
3381
3382 if (strcmp(args[*cur_arg + 1], "none") == 0)
3383 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
3384 else if (strcmp(args[*cur_arg + 1], "required") == 0)
3385 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
3386 else {
3387 if (err)
3388 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
3389 args[*cur_arg], args[*cur_arg + 1]);
3390 return ERR_ALERT | ERR_FATAL;
3391 }
3392
Evan Broderbe554312013-06-27 00:05:25 -07003393 return 0;
3394}
3395
3396/* parse the "verifyhost" server keyword */
3397static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3398{
3399 if (!*args[*cur_arg + 1]) {
3400 if (err)
3401 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
3402 return ERR_ALERT | ERR_FATAL;
3403 }
3404
3405 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
3406
Emeric Brunef42d922012-10-11 16:11:36 +02003407 return 0;
3408}
3409
Willy Tarreau7875d092012-09-10 08:20:03 +02003410/* Note: must not be declared <const> as its list will be overwritten.
3411 * Please take care of keeping this list alphabetically sorted.
3412 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003413static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Willy Tarreau80aca902013-01-07 15:42:20 +01003414 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3415 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3416 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3417 { "ssl_c_i_dn", smp_fetch_ssl_c_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3418 { "ssl_c_key_alg", smp_fetch_ssl_c_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3419 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3420 { "ssl_c_notbefore", smp_fetch_ssl_c_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3421 { "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3422 { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3423 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
James Votha051b4a2013-05-14 20:37:59 +02003424 { "ssl_c_sha1", smp_fetch_ssl_c_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01003425 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3426 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3427 { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3428 { "ssl_f_i_dn", smp_fetch_ssl_f_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3429 { "ssl_f_key_alg", smp_fetch_ssl_f_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3430 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3431 { "ssl_f_notbefore", smp_fetch_ssl_f_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3432 { "ssl_f_sig_alg", smp_fetch_ssl_f_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3433 { "ssl_f_s_dn", smp_fetch_ssl_f_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3434 { "ssl_f_serial", smp_fetch_ssl_f_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3435 { "ssl_f_version", smp_fetch_ssl_f_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3436 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3437 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3438 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3439 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3440 { "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 +02003441#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau80aca902013-01-07 15:42:20 +01003442 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003443#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003444#ifdef OPENSSL_ALPN_NEGOTIATED
3445 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3446#endif
Willy Tarreau80aca902013-01-07 15:42:20 +01003447 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3448 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3449 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_CBIN, SMP_USE_L5CLI },
3450 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreau7875d092012-09-10 08:20:03 +02003451 { NULL, NULL, 0, 0, 0 },
3452}};
3453
3454/* Note: must not be declared <const> as its list will be overwritten.
3455 * Please take care of keeping this list alphabetically sorted.
3456 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003457static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003458 { "ssl_c_i_dn", NULL, pat_parse_str, pat_match_str },
3459 { "ssl_c_key_alg", NULL, pat_parse_str, pat_match_str },
3460 { "ssl_c_notafter", NULL, pat_parse_str, pat_match_str },
3461 { "ssl_c_notbefore", NULL, pat_parse_str, pat_match_str },
3462 { "ssl_c_sig_alg", NULL, pat_parse_str, pat_match_str },
3463 { "ssl_c_s_dn", NULL, pat_parse_str, pat_match_str },
3464 { "ssl_c_serial", NULL, pat_parse_bin, pat_match_bin },
3465 { "ssl_f_i_dn", NULL, pat_parse_str, pat_match_str },
3466 { "ssl_f_key_alg", NULL, pat_parse_str, pat_match_str },
3467 { "ssl_f_notafter", NULL, pat_parse_str, pat_match_str },
3468 { "ssl_f_notbefore", NULL, pat_parse_str, pat_match_str },
3469 { "ssl_f_sig_alg", NULL, pat_parse_str, pat_match_str },
3470 { "ssl_f_s_dn", NULL, pat_parse_str, pat_match_str },
3471 { "ssl_f_serial", NULL, pat_parse_bin, pat_match_bin },
3472 { "ssl_fc_cipher", NULL, pat_parse_str, pat_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003473#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003474 { "ssl_fc_npn", NULL, pat_parse_str, pat_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003475#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003476#ifdef OPENSSL_ALPN_NEGOTIATED
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003477 { "ssl_fc_alpn", NULL, pat_parse_str, pat_match_str },
Willy Tarreauab861d32013-04-02 02:30:41 +02003478#endif
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003479 { "ssl_fc_protocol", NULL, pat_parse_str, pat_match_str },
3480 { "ssl_fc_sni", "ssl_fc_sni", pat_parse_str, pat_match_str },
3481 { "ssl_fc_sni_end", "ssl_fc_sni", pat_parse_str, pat_match_end },
3482 { "ssl_fc_sni_reg", "ssl_fc_sni", pat_parse_reg, pat_match_reg },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01003483 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02003484}};
3485
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003486/* Note: must not be declared <const> as its list will be overwritten.
3487 * Please take care of keeping this list alphabetically sorted, doing so helps
3488 * all code contributors.
3489 * Optional keywords are also declared with a NULL ->parse() function so that
3490 * the config parser can report an appropriate error when a known keyword was
3491 * not enabled.
3492 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02003493static struct bind_kw_list bind_kws = { "SSL", { }, {
Willy Tarreauab861d32013-04-02 02:30:41 +02003494 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003495 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003496 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
3497 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003498 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003499 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
3500 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003501 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003502 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003503 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
3504 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
3505 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
3506 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02003507 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
3508 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
3509 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
3510 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003511 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003512 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003513 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003514 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003515 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003516 { NULL, NULL, 0 },
3517}};
Emeric Brun46591952012-05-18 15:47:34 +02003518
Willy Tarreau92faadf2012-10-10 23:04:25 +02003519/* Note: must not be declared <const> as its list will be overwritten.
3520 * Please take care of keeping this list alphabetically sorted, doing so helps
3521 * all code contributors.
3522 * Optional keywords are also declared with a NULL ->parse() function so that
3523 * the config parser can report an appropriate error when a known keyword was
3524 * not enabled.
3525 */
3526static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02003527 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003528 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
3529 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02003530 { "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 +02003531 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003532 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
3533 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
3534 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
3535 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
3536 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
3537 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
3538 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
3539 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02003540 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003541 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02003542 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Evan Broderbe554312013-06-27 00:05:25 -07003543 { "verifyhost", srv_parse_verifyhost, 1, 0 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02003544 { NULL, NULL, 0, 0 },
3545}};
3546
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003547/* transport-layer operations for SSL sockets */
3548struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02003549 .snd_buf = ssl_sock_from_buf,
3550 .rcv_buf = ssl_sock_to_buf,
3551 .rcv_pipe = NULL,
3552 .snd_pipe = NULL,
3553 .shutr = NULL,
3554 .shutw = ssl_sock_shutw,
3555 .close = ssl_sock_close,
3556 .init = ssl_sock_init,
3557};
3558
3559__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02003560static void __ssl_sock_init(void)
3561{
Emeric Brun46591952012-05-18 15:47:34 +02003562 STACK_OF(SSL_COMP)* cm;
3563
3564 SSL_library_init();
3565 cm = SSL_COMP_get_compression_methods();
3566 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02003567 sample_register_fetches(&sample_fetch_keywords);
3568 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003569 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02003570 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02003571}
3572
3573/*
3574 * Local variables:
3575 * c-indent-level: 8
3576 * c-basic-offset: 8
3577 * End:
3578 */