blob: 0cfcca798bd7fab87194c63979c74606dbbd079d [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 Tarreau403edff2012-09-06 11:58:37 +020089static int sslconns = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +020090
91void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
92{
93 struct connection *conn = (struct connection *)SSL_get_app_data(ssl);
94 (void)ret; /* shut gcc stupid warning */
95
96 if (where & SSL_CB_HANDSHAKE_START) {
97 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreau20879a02012-12-03 16:32:10 +010098 if (conn->flags & CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +020099 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +0100100 conn->err_code = CO_ER_SSL_RENEG;
101 }
Emeric Brune1f38db2012-09-03 20:36:47 +0200102 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200103}
104
Emeric Brune64aef12012-09-21 13:15:06 +0200105/* Callback is called for each certificate of the chain during a verify
106 ok is set to 1 if preverify detect no error on current certificate.
107 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -0700108int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +0200109{
110 SSL *ssl;
111 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +0200112 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +0200113
114 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
115 conn = (struct connection *)SSL_get_app_data(ssl);
116
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200117 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +0200118
Emeric Brun81c00f02012-09-21 14:31:21 +0200119 if (ok) /* no errors */
120 return ok;
121
122 depth = X509_STORE_CTX_get_error_depth(x_store);
123 err = X509_STORE_CTX_get_error(x_store);
124
125 /* check if CA error needs to be ignored */
126 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200127 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
128 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
129 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +0200130 }
131
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100132 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
133 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +0200134 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100135 }
Emeric Brun81c00f02012-09-21 14:31:21 +0200136
Willy Tarreau20879a02012-12-03 16:32:10 +0100137 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +0200138 return 0;
139 }
140
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200141 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
142 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +0200143
Emeric Brun81c00f02012-09-21 14:31:21 +0200144 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100145 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
146 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +0200147 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100148 }
Emeric Brun81c00f02012-09-21 14:31:21 +0200149
Willy Tarreau20879a02012-12-03 16:32:10 +0100150 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +0200151 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +0200152}
153
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200154#ifdef OPENSSL_NPN_NEGOTIATED
155/* This callback is used so that the server advertises the list of
156 * negociable protocols for NPN.
157 */
158static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
159 unsigned int *len, void *arg)
160{
161 struct bind_conf *conf = arg;
162
163 *data = (const unsigned char *)conf->npn_str;
164 *len = conf->npn_len;
165 return SSL_TLSEXT_ERR_OK;
166}
167#endif
168
Willy Tarreauab861d32013-04-02 02:30:41 +0200169#ifdef OPENSSL_ALPN_NEGOTIATED
170/* This callback is used so that the server advertises the list of
171 * negociable protocols for ALPN.
172 */
173static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **data,
174 unsigned int *len, void *arg)
175{
176 struct bind_conf *conf = arg;
177
178 *data = (const unsigned char *)conf->alpn_str;
179 *len = conf->alpn_len;
180 return SSL_TLSEXT_ERR_OK;
181}
182#endif
183
Emeric Brunfc0421f2012-09-07 17:30:07 +0200184#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
185/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
186 * warning when no match is found, which implies the default (first) cert
187 * will keep being used.
188 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200189static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, struct bind_conf *s)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200190{
191 const char *servername;
192 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200193 struct ebmb_node *node, *n;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200194 int i;
195 (void)al; /* shut gcc stupid warning */
196
197 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100198 if (!servername) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200199 return (s->strict_sni ?
200 SSL_TLSEXT_ERR_ALERT_FATAL :
Emmanuel Hocdet79274e22013-05-31 12:47:44 +0200201 SSL_TLSEXT_ERR_NOACK);
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100202 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200203
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100204 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200205 if (!servername[i])
206 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100207 trash.str[i] = tolower(servername[i]);
208 if (!wildp && (trash.str[i] == '.'))
209 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200210 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100211 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200212
213 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100214 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200215
216 /* lookup a not neg filter */
217 for (n = node; n; n = ebmb_next_dup(n)) {
218 if (!container_of(n, struct sni_ctx, name)->neg) {
219 node = n;
220 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100221 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200222 }
223 if (!node && wildp) {
224 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +0200225 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200226 }
227 if (!node || container_of(node, struct sni_ctx, name)->neg) {
228 return (s->strict_sni ?
229 SSL_TLSEXT_ERR_ALERT_FATAL :
230 SSL_TLSEXT_ERR_ALERT_WARNING);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200231 }
232
233 /* switch ctx */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200234 SSL_set_SSL_CTX(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200235 return SSL_TLSEXT_ERR_OK;
236}
237#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
238
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200239#ifndef OPENSSL_NO_DH
240/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
241 if an error occured, and 0 if parameter not found. */
242int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
243{
244 int ret = -1;
245 BIO *in;
246 DH *dh = NULL;
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200247 /* If not present, use parameters generated using 'openssl dhparam 1024 -C':
248 * -----BEGIN DH PARAMETERS-----
249 * MIGHAoGBAJJAJDXDoS5E03MNjnjK36eOL1tRqVa/9NuOVlI+lpXmPjJQbP65EvKn
250 * fSLnG7VMhoCJO4KtG88zf393ltP7loGB2bofcDSr+x+XsxBM8yA/Zj6BmQt+CQ9s
251 * TF7hoOV+wXTT6ErZ5y5qx9pq6hLfKXwTGFT78hrE6HnCO7xgtPdTAgEC
252 * -----END DH PARAMETERS-----
253 */
254 static const unsigned char dh1024_p[] = {
255 0x92, 0x40, 0x24, 0x35, 0xC3, 0xA1, 0x2E, 0x44, 0xD3, 0x73, 0x0D, 0x8E,
256 0x78, 0xCA, 0xDF, 0xA7, 0x8E, 0x2F, 0x5B, 0x51, 0xA9, 0x56, 0xBF, 0xF4,
257 0xDB, 0x8E, 0x56, 0x52, 0x3E, 0x96, 0x95, 0xE6, 0x3E, 0x32, 0x50, 0x6C,
258 0xFE, 0xB9, 0x12, 0xF2, 0xA7, 0x7D, 0x22, 0xE7, 0x1B, 0xB5, 0x4C, 0x86,
259 0x80, 0x89, 0x3B, 0x82, 0xAD, 0x1B, 0xCF, 0x33, 0x7F, 0x7F, 0x77, 0x96,
260 0xD3, 0xFB, 0x96, 0x81, 0x81, 0xD9, 0xBA, 0x1F, 0x70, 0x34, 0xAB, 0xFB,
261 0x1F, 0x97, 0xB3, 0x10, 0x4C, 0xF3, 0x20, 0x3F, 0x66, 0x3E, 0x81, 0x99,
262 0x0B, 0x7E, 0x09, 0x0F, 0x6C, 0x4C, 0x5E, 0xE1, 0xA0, 0xE5, 0x7E, 0xC1,
263 0x74, 0xD3, 0xE8, 0x4A, 0xD9, 0xE7, 0x2E, 0x6A, 0xC7, 0xDA, 0x6A, 0xEA,
264 0x12, 0xDF, 0x29, 0x7C, 0x13, 0x18, 0x54, 0xFB, 0xF2, 0x1A, 0xC4, 0xE8,
265 0x79, 0xC2, 0x3B, 0xBC, 0x60, 0xB4, 0xF7, 0x53,
266 };
267 static const unsigned char dh1024_g[] = {
268 0x02,
269 };
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200270
271 in = BIO_new(BIO_s_file());
272 if (in == NULL)
273 goto end;
274
275 if (BIO_read_filename(in, file) <= 0)
276 goto end;
277
278 dh = PEM_read_bio_DHparams(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200279 if (!dh) {
280 /* Clear openssl global errors stack */
281 ERR_clear_error();
282
283 dh = DH_new();
284 if (dh == NULL)
285 goto end;
286
287 dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
288 if (dh->p == NULL)
289 goto end;
290
291 dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
292 if (dh->g == NULL)
293 goto end;
294
295 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200296 }
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200297 else
298 ret = 1;
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200299
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200300 SSL_CTX_set_tmp_dh(ctx, dh);
Emeric Brun644cde02012-12-14 11:21:13 +0100301
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200302end:
303 if (dh)
304 DH_free(dh);
305
306 if (in)
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200307 BIO_free(in);
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200308
309 return ret;
310}
311#endif
312
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200313static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100314{
315 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200316 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100317
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200318 if (*name == '!') {
319 neg = 1;
320 name++;
321 }
322 if (*name == '*') {
323 wild = 1;
324 name++;
325 }
326 /* !* filter is a nop */
327 if (neg && wild)
328 return order;
329 if (*name) {
330 int j, len;
331 len = strlen(name);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100332 sc = malloc(sizeof(struct sni_ctx) + len + 1);
333 for (j = 0; j < len; j++)
334 sc->name.key[j] = tolower(name[j]);
335 sc->name.key[len] = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100336 sc->ctx = ctx;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200337 sc->order = order++;
338 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100339 if (wild)
340 ebst_insert(&s->sni_w_ctx, &sc->name);
341 else
342 ebst_insert(&s->sni_ctx, &sc->name);
343 }
344 return order;
345}
346
Emeric Brunfc0421f2012-09-07 17:30:07 +0200347/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
348 * an early error happens and the caller must call SSL_CTX_free() by itelf.
349 */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200350static 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 +0200351{
352 BIO *in;
353 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200354 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200355 int ret = -1;
356 int order = 0;
357 X509_NAME *xname;
358 char *str;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200359#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
360 STACK_OF(GENERAL_NAME) *names;
361#endif
362
363 in = BIO_new(BIO_s_file());
364 if (in == NULL)
365 goto end;
366
367 if (BIO_read_filename(in, file) <= 0)
368 goto end;
369
370 x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
371 if (x == NULL)
372 goto end;
373
Emeric Brun50bcecc2013-04-22 13:05:23 +0200374 if (fcount) {
375 while (fcount--)
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200376 order = ssl_sock_add_cert_sni(ctx, s, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100377 }
378 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200379#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100380 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
381 if (names) {
382 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
383 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
384 if (name->type == GEN_DNS) {
385 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200386 order = ssl_sock_add_cert_sni(ctx, s, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100387 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200388 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200389 }
390 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100391 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200392 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200393#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100394 xname = X509_get_subject_name(x);
395 i = -1;
396 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
397 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
398 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200399 order = ssl_sock_add_cert_sni(ctx, s, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100400 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200401 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200402 }
403 }
404
405 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
406 if (!SSL_CTX_use_certificate(ctx, x))
407 goto end;
408
409 if (ctx->extra_certs != NULL) {
410 sk_X509_pop_free(ctx->extra_certs, X509_free);
411 ctx->extra_certs = NULL;
412 }
413
414 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata))) {
415 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
416 X509_free(ca);
417 goto end;
418 }
419 }
420
421 err = ERR_get_error();
422 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
423 /* we successfully reached the last cert in the file */
424 ret = 1;
425 }
426 ERR_clear_error();
427
428end:
429 if (x)
430 X509_free(x);
431
432 if (in)
433 BIO_free(in);
434
435 return ret;
436}
437
Emeric Brun50bcecc2013-04-22 13:05:23 +0200438static 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 +0200439{
440 int ret;
441 SSL_CTX *ctx;
442
443 ctx = SSL_CTX_new(SSLv23_server_method());
444 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200445 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
446 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200447 return 1;
448 }
449
450 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200451 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
452 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200453 SSL_CTX_free(ctx);
454 return 1;
455 }
456
Emeric Brun50bcecc2013-04-22 13:05:23 +0200457 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200458 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200459 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
460 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200461 if (ret < 0) /* serious error, must do that ourselves */
462 SSL_CTX_free(ctx);
463 return 1;
464 }
Emeric Brun61694ab2012-10-26 13:35:33 +0200465
466 if (SSL_CTX_check_private_key(ctx) <= 0) {
467 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
468 err && *err ? *err : "", path);
469 return 1;
470 }
471
Emeric Brunfc0421f2012-09-07 17:30:07 +0200472 /* we must not free the SSL_CTX anymore below, since it's already in
473 * the tree, so it will be discovered and cleaned in time.
474 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200475#ifndef OPENSSL_NO_DH
476 ret = ssl_sock_load_dh_params(ctx, path);
477 if (ret < 0) {
478 if (err)
479 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
480 *err ? *err : "", path);
481 return 1;
482 }
483#endif
484
Emeric Brunfc0421f2012-09-07 17:30:07 +0200485#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200486 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200487 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
488 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +0200489 return 1;
490 }
491#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200492 if (!bind_conf->default_ctx)
493 bind_conf->default_ctx = ctx;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200494
495 return 0;
496}
497
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200498int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200499{
500 struct dirent *de;
501 DIR *dir;
502 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +0100503 char *end;
504 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200505 int cfgerr = 0;
506
507 if (!(dir = opendir(path)))
Emeric Brun50bcecc2013-04-22 13:05:23 +0200508 return ssl_sock_load_cert_file(path, bind_conf, curproxy, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200509
510 /* strip trailing slashes, including first one */
511 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
512 *end = 0;
513
Emeric Brunfc0421f2012-09-07 17:30:07 +0200514 while ((de = readdir(dir))) {
Willy Tarreauee2663b2012-12-06 11:36:59 +0100515 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200516 if (stat(fp, &buf) != 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200517 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
518 err && *err ? *err : "", fp, strerror(errno));
Emeric Brunfc0421f2012-09-07 17:30:07 +0200519 cfgerr++;
520 continue;
521 }
522 if (!S_ISREG(buf.st_mode))
523 continue;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200524 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, curproxy, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200525 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200526 closedir(dir);
527 return cfgerr;
528}
529
Thierry Fournier383085f2013-01-24 14:15:43 +0100530/* Make sure openssl opens /dev/urandom before the chroot. The work is only
531 * done once. Zero is returned if the operation fails. No error is returned
532 * if the random is said as not implemented, because we expect that openssl
533 * will use another method once needed.
534 */
535static int ssl_initialize_random()
536{
537 unsigned char random;
538 static int random_initialized = 0;
539
540 if (!random_initialized && RAND_bytes(&random, 1) != 0)
541 random_initialized = 1;
542
543 return random_initialized;
544}
545
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100546int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
547{
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200548 char thisline[LINESIZE];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100549 FILE *f;
550 int linenum = 0;
551 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100552
Willy Tarreauad1731d2013-04-02 17:35:58 +0200553 if ((f = fopen(file, "r")) == NULL) {
554 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100555 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200556 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100557
558 while (fgets(thisline, sizeof(thisline), f) != NULL) {
559 int arg;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200560 int newarg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100561 char *end;
562 char *args[MAX_LINE_ARGS + 1];
563 char *line = thisline;
564
565 linenum++;
566 end = line + strlen(line);
567 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
568 /* Check if we reached the limit and the last char is not \n.
569 * Watch out for the last line without the terminating '\n'!
570 */
Willy Tarreauad1731d2013-04-02 17:35:58 +0200571 memprintf(err, "line %d too long in file '%s', limit is %d characters",
572 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100573 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200574 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100575 }
576
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100577 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200578 newarg = 1;
579 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100580 if (*line == '#' || *line == '\n' || *line == '\r') {
581 /* end of string, end of loop */
582 *line = 0;
583 break;
584 }
585 else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +0200586 newarg = 1;
587 *line = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100588 }
Emeric Brun50bcecc2013-04-22 13:05:23 +0200589 else if (newarg) {
590 if (arg == MAX_LINE_ARGS) {
591 memprintf(err, "too many args on line %d in file '%s'.",
592 linenum, file);
593 cfgerr = 1;
594 break;
595 }
596 newarg = 0;
597 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100598 }
Emeric Brun50bcecc2013-04-22 13:05:23 +0200599 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100600 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200601 if (cfgerr)
602 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200603
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100604 /* empty line */
Emeric Brun50bcecc2013-04-22 13:05:23 +0200605 if (!arg)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100606 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100607
Emeric Brun50bcecc2013-04-22 13:05:23 +0200608 cfgerr = ssl_sock_load_cert_file(args[0], bind_conf, curproxy, &args[1], arg-1, err);
Willy Tarreauad1731d2013-04-02 17:35:58 +0200609 if (cfgerr) {
610 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100611 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200612 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100613 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100614 fclose(f);
615 return cfgerr;
616}
617
Emeric Brunfc0421f2012-09-07 17:30:07 +0200618#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
619#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
620#endif
621
622#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
623#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
Willy Tarreau7d588ee2012-11-26 18:47:31 +0100624#define SSL_renegotiate_pending(arg) 0
Emeric Brunfc0421f2012-09-07 17:30:07 +0200625#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200626#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
627#define SSL_OP_SINGLE_ECDH_USE 0
628#endif
Emeric Brun2d0c4822012-10-02 13:45:20 +0200629#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
630#define SSL_OP_NO_TICKET 0
631#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200632#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
633#define SSL_OP_NO_COMPRESSION 0
634#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +0200635#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
636#define SSL_OP_NO_TLSv1_1 0
637#endif
638#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
639#define SSL_OP_NO_TLSv1_2 0
640#endif
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200641#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
642#define SSL_OP_SINGLE_DH_USE 0
643#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200644#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
645#define SSL_OP_SINGLE_ECDH_USE 0
646#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200647#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
648#define SSL_MODE_RELEASE_BUFFERS 0
649#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200650int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy *curproxy)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200651{
652 int cfgerr = 0;
653 int ssloptions =
654 SSL_OP_ALL | /* all known workarounds for bugs */
655 SSL_OP_NO_SSLv2 |
656 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200657 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +0200658 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +0200659 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
660 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200661 int sslmode =
662 SSL_MODE_ENABLE_PARTIAL_WRITE |
663 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
664 SSL_MODE_RELEASE_BUFFERS;
665
Thierry Fournier383085f2013-01-24 14:15:43 +0100666 /* Make sure openssl opens /dev/urandom before the chroot */
667 if (!ssl_initialize_random()) {
668 Alert("OpenSSL random data generator initialization failed.\n");
669 cfgerr++;
670 }
671
Emeric Brun89675492012-10-05 13:48:26 +0200672 if (bind_conf->ssl_options & BC_SSL_O_NO_SSLV3)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200673 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brun89675492012-10-05 13:48:26 +0200674 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV10)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200675 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun89675492012-10-05 13:48:26 +0200676 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV11)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200677 ssloptions |= SSL_OP_NO_TLSv1_1;
Emeric Brun89675492012-10-05 13:48:26 +0200678 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV12)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200679 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun89675492012-10-05 13:48:26 +0200680 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
Emeric Brun2d0c4822012-10-02 13:45:20 +0200681 ssloptions |= SSL_OP_NO_TICKET;
Emeric Brun2cb7ae52012-10-05 14:14:21 +0200682 if (bind_conf->ssl_options & BC_SSL_O_USE_SSLV3)
683 SSL_CTX_set_ssl_version(ctx, SSLv3_server_method());
684 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV10)
685 SSL_CTX_set_ssl_version(ctx, TLSv1_server_method());
686#if SSL_OP_NO_TLSv1_1
687 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV11)
688 SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method());
689#endif
690#if SSL_OP_NO_TLSv1_2
691 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV12)
692 SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method());
693#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200694
695 SSL_CTX_set_options(ctx, ssloptions);
696 SSL_CTX_set_mode(ctx, sslmode);
Evan Broderbe554312013-06-27 00:05:25 -0700697 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 +0200698 if (bind_conf->verify & SSL_VERIFY_PEER) {
Emeric Brunfb510ea2012-10-05 12:00:26 +0200699 if (bind_conf->ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200700 /* load CAfile to verify */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200701 if (!SSL_CTX_load_verify_locations(ctx, bind_conf->ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200702 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200703 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200704 cfgerr++;
705 }
706 /* set CA names fo client cert request, function returns void */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200707 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(bind_conf->ca_file));
Emeric Brund94b3fe2012-09-20 18:23:56 +0200708 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200709#ifdef X509_V_FLAG_CRL_CHECK
Emeric Brunfb510ea2012-10-05 12:00:26 +0200710 if (bind_conf->crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200711 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
712
Emeric Brunfb510ea2012-10-05 12:00:26 +0200713 if (!store || !X509_STORE_load_locations(store, bind_conf->crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200714 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200715 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200716 cfgerr++;
717 }
Emeric Brun561e5742012-10-02 15:20:55 +0200718 else {
719 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
720 }
Emeric Brund94b3fe2012-09-20 18:23:56 +0200721 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200722#endif
Emeric Brun644cde02012-12-14 11:21:13 +0100723 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +0200724 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200725
Emeric Brun4f65bff2012-11-16 15:11:00 +0100726 if (global.tune.ssllifetime)
727 SSL_CTX_set_timeout(ctx, global.tune.ssllifetime);
728
Emeric Brunfc0421f2012-09-07 17:30:07 +0200729 shared_context_set_cache(ctx);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200730 if (bind_conf->ciphers &&
731 !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200732 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 +0200733 curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200734 cfgerr++;
735 }
736
737 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200738#ifdef OPENSSL_NPN_NEGOTIATED
739 if (bind_conf->npn_str)
740 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
741#endif
Willy Tarreauab861d32013-04-02 02:30:41 +0200742#ifdef OPENSSL_ALPN_NEGOTIATED
743 if (bind_conf->alpn_str)
744 SSL_CTX_set_alpn_advertised_cb(ctx, ssl_sock_advertise_alpn_protos, bind_conf);
745#endif
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200746
Emeric Brunfc0421f2012-09-07 17:30:07 +0200747#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
748 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200749 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200750#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200751#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emeric Brun6924ef82013-03-06 14:08:53 +0100752 {
Emeric Brun2b58d042012-09-20 17:10:03 +0200753 int i;
754 EC_KEY *ecdh;
755
Emeric Brun6924ef82013-03-06 14:08:53 +0100756 i = OBJ_sn2nid(bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE);
Emeric Brun2b58d042012-09-20 17:10:03 +0200757 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
758 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 +0100759 curproxy->id, bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE,
760 bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +0200761 cfgerr++;
762 }
763 else {
764 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
765 EC_KEY_free(ecdh);
766 }
767 }
768#endif
769
Emeric Brunfc0421f2012-09-07 17:30:07 +0200770 return cfgerr;
771}
772
Evan Broderbe554312013-06-27 00:05:25 -0700773static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
774{
775 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
776 size_t prefixlen, suffixlen;
777
778 /* Trivial case */
779 if (strcmp(pattern, hostname) == 0)
780 return 1;
781
Evan Broderbe554312013-06-27 00:05:25 -0700782 /* The rest of this logic is based on RFC 6125, section 6.4.3
783 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
784
Emeric Bruna848dae2013-10-08 11:27:28 +0200785 pattern_wildcard = NULL;
786 pattern_left_label_end = pattern;
787 while (*pattern_left_label_end != '.') {
788 switch (*pattern_left_label_end) {
789 case 0:
790 /* End of label not found */
791 return 0;
792 case '*':
793 /* If there is more than one wildcards */
794 if (pattern_wildcard)
795 return 0;
796 pattern_wildcard = pattern_left_label_end;
797 break;
798 }
799 pattern_left_label_end++;
800 }
801
802 /* If it's not trivial and there is no wildcard, it can't
803 * match */
804 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -0700805 return 0;
806
807 /* Make sure all labels match except the leftmost */
808 hostname_left_label_end = strchr(hostname, '.');
809 if (!hostname_left_label_end
810 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
811 return 0;
812
813 /* Make sure the leftmost label of the hostname is long enough
814 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +0200815 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -0700816 return 0;
817
818 /* Finally compare the string on either side of the
819 * wildcard */
820 prefixlen = pattern_wildcard - pattern;
821 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +0200822 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
823 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -0700824 return 0;
825
826 return 1;
827}
828
829static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
830{
831 SSL *ssl;
832 struct connection *conn;
833 char *servername;
834
835 int depth;
836 X509 *cert;
837 STACK_OF(GENERAL_NAME) *alt_names;
838 int i;
839 X509_NAME *cert_subject;
840 char *str;
841
842 if (ok == 0)
843 return ok;
844
845 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
846 conn = (struct connection *)SSL_get_app_data(ssl);
847
848 servername = objt_server(conn->target)->ssl_ctx.verify_host;
849
850 /* We only need to verify the CN on the actual server cert,
851 * not the indirect CAs */
852 depth = X509_STORE_CTX_get_error_depth(ctx);
853 if (depth != 0)
854 return ok;
855
856 /* At this point, the cert is *not* OK unless we can find a
857 * hostname match */
858 ok = 0;
859
860 cert = X509_STORE_CTX_get_current_cert(ctx);
861 /* It seems like this might happen if verify peer isn't set */
862 if (!cert)
863 return ok;
864
865 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
866 if (alt_names) {
867 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
868 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
869 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +0200870#if OPENSSL_VERSION_NUMBER < 0x00907000L
871 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
872#else
Evan Broderbe554312013-06-27 00:05:25 -0700873 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +0200874#endif
Evan Broderbe554312013-06-27 00:05:25 -0700875 ok = ssl_sock_srv_hostcheck(str, servername);
876 OPENSSL_free(str);
877 }
878 }
879 }
Emeric Brun4ad50a42013-09-17 15:19:54 +0200880 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -0700881 }
882
883 cert_subject = X509_get_subject_name(cert);
884 i = -1;
885 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
886 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
887 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
888 ok = ssl_sock_srv_hostcheck(str, servername);
889 OPENSSL_free(str);
890 }
891 }
892
893 return ok;
894}
895
Emeric Brun94324a42012-10-11 14:00:19 +0200896/* prepare ssl context from servers options. Returns an error count */
897int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
898{
899 int cfgerr = 0;
900 int options =
901 SSL_OP_ALL | /* all known workarounds for bugs */
902 SSL_OP_NO_SSLv2 |
903 SSL_OP_NO_COMPRESSION;
904 int mode =
905 SSL_MODE_ENABLE_PARTIAL_WRITE |
906 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
907 SSL_MODE_RELEASE_BUFFERS;
908
Thierry Fournier383085f2013-01-24 14:15:43 +0100909 /* Make sure openssl opens /dev/urandom before the chroot */
910 if (!ssl_initialize_random()) {
911 Alert("OpenSSL random data generator initialization failed.\n");
912 cfgerr++;
913 }
914
Emeric Brun94324a42012-10-11 14:00:19 +0200915 /* Initiate SSL context for current server */
916 srv->ssl_ctx.reused_sess = NULL;
917 if (srv->use_ssl)
918 srv->xprt = &ssl_sock;
919 if (srv->check.use_ssl)
Simon Horman66183002013-02-23 10:16:43 +0900920 srv->check_common.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +0200921
922 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
923 if (!srv->ssl_ctx.ctx) {
924 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
925 proxy_type_str(curproxy), curproxy->id,
926 srv->id);
927 cfgerr++;
928 return cfgerr;
929 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200930 if (srv->ssl_ctx.client_crt) {
931 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
932 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
933 proxy_type_str(curproxy), curproxy->id,
934 srv->id, srv->ssl_ctx.client_crt);
935 cfgerr++;
936 }
937 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
938 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
939 proxy_type_str(curproxy), curproxy->id,
940 srv->id, srv->ssl_ctx.client_crt);
941 cfgerr++;
942 }
943 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
944 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
945 proxy_type_str(curproxy), curproxy->id,
946 srv->id, srv->ssl_ctx.client_crt);
947 cfgerr++;
948 }
949 }
Emeric Brun94324a42012-10-11 14:00:19 +0200950
951 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
952 options |= SSL_OP_NO_SSLv3;
953 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
954 options |= SSL_OP_NO_TLSv1;
955 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
956 options |= SSL_OP_NO_TLSv1_1;
957 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
958 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200959 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
960 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200961 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
962 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
963 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
964 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
965#if SSL_OP_NO_TLSv1_1
966 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
967 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
968#endif
969#if SSL_OP_NO_TLSv1_2
970 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
971 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
972#endif
973
974 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
975 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Evan Broderbe554312013-06-27 00:05:25 -0700976 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
977 srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE,
978 srv->ssl_ctx.verify_host ? ssl_sock_srv_verifycbk : NULL);
Emeric Brunef42d922012-10-11 16:11:36 +0200979 if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
980 if (srv->ssl_ctx.ca_file) {
981 /* load CAfile to verify */
982 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
983 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
984 curproxy->id, srv->id,
985 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
986 cfgerr++;
987 }
988 }
989#ifdef X509_V_FLAG_CRL_CHECK
990 if (srv->ssl_ctx.crl_file) {
991 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
992
993 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
994 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
995 curproxy->id, srv->id,
996 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
997 cfgerr++;
998 }
999 else {
1000 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
1001 }
1002 }
1003#endif
1004 }
1005
Emeric Brun4f65bff2012-11-16 15:11:00 +01001006 if (global.tune.ssllifetime)
1007 SSL_CTX_set_timeout(srv->ssl_ctx.ctx, global.tune.ssllifetime);
1008
Emeric Brun94324a42012-10-11 14:00:19 +02001009 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
1010 if (srv->ssl_ctx.ciphers &&
1011 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
1012 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
1013 curproxy->id, srv->id,
1014 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
1015 cfgerr++;
1016 }
1017
1018 return cfgerr;
1019}
1020
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001021/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02001022 * be NULL, in which case nothing is done. Returns the number of errors
1023 * encountered.
1024 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001025int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001026{
1027 struct ebmb_node *node;
1028 struct sni_ctx *sni;
1029 int err = 0;
1030
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001031 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001032 return 0;
1033
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001034 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001035 while (node) {
1036 sni = ebmb_entry(node, struct sni_ctx, name);
1037 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001038 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001039 node = ebmb_next(node);
1040 }
1041
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001042 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001043 while (node) {
1044 sni = ebmb_entry(node, struct sni_ctx, name);
1045 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001046 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001047 node = ebmb_next(node);
1048 }
1049 return err;
1050}
1051
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001052/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02001053 * be NULL, in which case nothing is done. The default_ctx is nullified too.
1054 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001055void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001056{
1057 struct ebmb_node *node, *back;
1058 struct sni_ctx *sni;
1059
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001060 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001061 return;
1062
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001063 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001064 while (node) {
1065 sni = ebmb_entry(node, struct sni_ctx, name);
1066 back = ebmb_next(node);
1067 ebmb_delete(node);
1068 if (!sni->order) /* only free the CTX on its first occurrence */
1069 SSL_CTX_free(sni->ctx);
1070 free(sni);
1071 node = back;
1072 }
1073
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001074 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001075 while (node) {
1076 sni = ebmb_entry(node, struct sni_ctx, name);
1077 back = ebmb_next(node);
1078 ebmb_delete(node);
1079 if (!sni->order) /* only free the CTX on its first occurrence */
1080 SSL_CTX_free(sni->ctx);
1081 free(sni);
1082 node = back;
1083 }
1084
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001085 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02001086}
1087
Emeric Brun46591952012-05-18 15:47:34 +02001088/*
1089 * This function is called if SSL * context is not yet allocated. The function
1090 * is designed to be called before any other data-layer operation and sets the
1091 * handshake flag on the connection. It is safe to call it multiple times.
1092 * It returns 0 on success and -1 in error case.
1093 */
1094static int ssl_sock_init(struct connection *conn)
1095{
1096 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001097 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001098 return 0;
1099
Willy Tarreauf79c8172013-10-21 16:30:56 +02001100 if (!(conn->flags & CO_FL_CTRL_READY))
1101 return 0;
1102
Willy Tarreau20879a02012-12-03 16:32:10 +01001103 if (global.maxsslconn && sslconns >= global.maxsslconn) {
1104 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02001105 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001106 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001107
Emeric Brun46591952012-05-18 15:47:34 +02001108 /* If it is in client mode initiate SSL session
1109 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001110 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001111 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001112 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001113 if (!conn->xprt_ctx) {
1114 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001115 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001116 }
Emeric Brun46591952012-05-18 15:47:34 +02001117
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001118 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001119 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1120 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001121
1122 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001123 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001124
Evan Broderbe554312013-06-27 00:05:25 -07001125 /* set connection pointer */
1126 SSL_set_app_data(conn->xprt_ctx, conn);
1127
Emeric Brun46591952012-05-18 15:47:34 +02001128 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001129 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001130
1131 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001132 return 0;
1133 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001134 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001135 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001136 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001137 if (!conn->xprt_ctx) {
1138 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001139 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001140 }
Emeric Brun46591952012-05-18 15:47:34 +02001141
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001142 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001143
1144 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001145 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001146
Emeric Brune1f38db2012-09-03 20:36:47 +02001147 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001148 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +02001149
Emeric Brun46591952012-05-18 15:47:34 +02001150 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001151 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001152
1153 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001154 return 0;
1155 }
1156 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01001157 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02001158 return -1;
1159}
1160
1161
1162/* This is the callback which is used when an SSL handshake is pending. It
1163 * updates the FD status if it wants some polling before being called again.
1164 * It returns 0 if it fails in a fatal way or needs to poll to go further,
1165 * otherwise it returns non-zero and removes itself from the connection's
1166 * flags (the bit is provided in <flag> by the caller).
1167 */
1168int ssl_sock_handshake(struct connection *conn, unsigned int flag)
1169{
1170 int ret;
1171
Willy Tarreauf79c8172013-10-21 16:30:56 +02001172 if (!(conn->flags & CO_FL_CTRL_READY))
1173 return 0;
1174
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001175 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001176 goto out_error;
1177
Emeric Brun674b7432012-11-08 19:21:55 +01001178 /* If we use SSL_do_handshake to process a reneg initiated by
1179 * the remote peer, it sometimes returns SSL_ERROR_SSL.
1180 * Usually SSL_write and SSL_read are used and process implicitly
1181 * the reneg handshake.
1182 * Here we use SSL_peek as a workaround for reneg.
1183 */
1184 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
1185 char c;
1186
1187 ret = SSL_peek(conn->xprt_ctx, &c, 1);
1188 if (ret <= 0) {
1189 /* handshake may have not been completed, let's find why */
1190 ret = SSL_get_error(conn->xprt_ctx, ret);
1191 if (ret == SSL_ERROR_WANT_WRITE) {
1192 /* SSL handshake needs to write, L4 connection may not be ready */
1193 __conn_sock_stop_recv(conn);
1194 __conn_sock_poll_send(conn);
1195 return 0;
1196 }
1197 else if (ret == SSL_ERROR_WANT_READ) {
1198 /* handshake may have been completed but we have
1199 * no more data to read.
1200 */
1201 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
1202 ret = 1;
1203 goto reneg_ok;
1204 }
1205 /* SSL handshake needs to read, L4 connection is ready */
1206 if (conn->flags & CO_FL_WAIT_L4_CONN)
1207 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1208 __conn_sock_stop_send(conn);
1209 __conn_sock_poll_recv(conn);
1210 return 0;
1211 }
1212 else if (ret == SSL_ERROR_SYSCALL) {
1213 /* if errno is null, then connection was successfully established */
1214 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1215 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001216 if (!conn->err_code) {
1217 if (!((SSL *)conn->xprt_ctx)->packet_length)
1218 if (!errno)
1219 conn->err_code = CO_ER_SSL_EMPTY;
1220 else
1221 conn->err_code = CO_ER_SSL_ABORT;
1222 else
1223 conn->err_code = CO_ER_SSL_HANDSHAKE;
1224 }
Emeric Brun674b7432012-11-08 19:21:55 +01001225 goto out_error;
1226 }
1227 else {
1228 /* Fail on all other handshake errors */
1229 /* Note: OpenSSL may leave unread bytes in the socket's
1230 * buffer, causing an RST to be emitted upon close() on
1231 * TCP sockets. We first try to drain possibly pending
1232 * data to avoid this as much as possible.
1233 */
Willy Tarreau46be2e52014-01-20 12:10:52 +01001234 conn_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01001235 if (!conn->err_code)
1236 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01001237 goto out_error;
1238 }
1239 }
1240 /* read some data: consider handshake completed */
1241 goto reneg_ok;
1242 }
1243
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001244 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001245 if (ret != 1) {
1246 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001247 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001248
1249 if (ret == SSL_ERROR_WANT_WRITE) {
1250 /* SSL handshake needs to write, L4 connection may not be ready */
1251 __conn_sock_stop_recv(conn);
1252 __conn_sock_poll_send(conn);
1253 return 0;
1254 }
1255 else if (ret == SSL_ERROR_WANT_READ) {
1256 /* SSL handshake needs to read, L4 connection is ready */
1257 if (conn->flags & CO_FL_WAIT_L4_CONN)
1258 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1259 __conn_sock_stop_send(conn);
1260 __conn_sock_poll_recv(conn);
1261 return 0;
1262 }
Willy Tarreau89230192012-09-28 20:22:13 +02001263 else if (ret == SSL_ERROR_SYSCALL) {
1264 /* if errno is null, then connection was successfully established */
1265 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1266 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001267
1268 if (!((SSL *)conn->xprt_ctx)->packet_length)
1269 if (!errno)
1270 conn->err_code = CO_ER_SSL_EMPTY;
1271 else
1272 conn->err_code = CO_ER_SSL_ABORT;
1273 else
1274 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +02001275 goto out_error;
1276 }
Emeric Brun46591952012-05-18 15:47:34 +02001277 else {
1278 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02001279 /* Note: OpenSSL may leave unread bytes in the socket's
1280 * buffer, causing an RST to be emitted upon close() on
1281 * TCP sockets. We first try to drain possibly pending
1282 * data to avoid this as much as possible.
1283 */
Willy Tarreau46be2e52014-01-20 12:10:52 +01001284 conn_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01001285 if (!conn->err_code)
1286 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001287 goto out_error;
1288 }
1289 }
1290
Emeric Brun674b7432012-11-08 19:21:55 +01001291reneg_ok:
1292
Emeric Brun46591952012-05-18 15:47:34 +02001293 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001294 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001295 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +02001296 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001297 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1298 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001299
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001300 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001301 }
1302 }
1303
1304 /* The connection is now established at both layers, it's time to leave */
1305 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1306 return 1;
1307
1308 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001309 /* Clear openssl global errors stack */
1310 ERR_clear_error();
1311
Emeric Brun9fa89732012-10-04 17:09:56 +02001312 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001313 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1314 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1315 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001316 }
1317
Emeric Brun46591952012-05-18 15:47:34 +02001318 /* Fail on all other handshake errors */
1319 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001320 if (!conn->err_code)
1321 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001322 return 0;
1323}
1324
1325/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01001326 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02001327 * buffer wraps, in which case a second call may be performed. The connection's
1328 * flags are updated with whatever special event is detected (error, read0,
1329 * empty). The caller is responsible for taking care of those events and
1330 * avoiding the call if inappropriate. The function does not call the
1331 * connection's polling update function, so the caller is responsible for this.
1332 */
1333static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1334{
1335 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01001336 int try;
Emeric Brun46591952012-05-18 15:47:34 +02001337
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001338 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001339 goto out_error;
1340
1341 if (conn->flags & CO_FL_HANDSHAKE)
1342 /* a handshake was requested */
1343 return 0;
1344
Willy Tarreauabf08d92014-01-14 11:31:27 +01001345 /* let's realign the buffer to optimize I/O */
1346 if (buffer_empty(buf))
Emeric Brun46591952012-05-18 15:47:34 +02001347 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02001348
1349 /* read the largest possible block. For this, we perform only one call
1350 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1351 * in which case we accept to do it once again. A new attempt is made on
1352 * EINTR too.
1353 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01001354 while (count > 0) {
Willy Tarreauabf08d92014-01-14 11:31:27 +01001355 /* first check if we have some room after p+i */
1356 try = buf->data + buf->size - (buf->p + buf->i);
1357 /* otherwise continue between data and p-o */
1358 if (try <= 0) {
1359 try = buf->p - (buf->data + buf->o);
1360 if (try <= 0)
1361 break;
1362 }
1363 if (try > count)
1364 try = count;
1365
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001366 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001367 if (conn->flags & CO_FL_ERROR) {
1368 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001369 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001370 }
Emeric Brun46591952012-05-18 15:47:34 +02001371 if (ret > 0) {
1372 buf->i += ret;
1373 done += ret;
1374 if (ret < try)
1375 break;
1376 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02001377 }
1378 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001379 ret = SSL_get_error(conn->xprt_ctx, ret);
1380 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001381 /* error on protocol or underlying transport */
1382 if ((ret != SSL_ERROR_SYSCALL)
1383 || (errno && (errno != EAGAIN)))
1384 conn->flags |= CO_FL_ERROR;
1385
Emeric Brun644cde02012-12-14 11:21:13 +01001386 /* Clear openssl global errors stack */
1387 ERR_clear_error();
1388 }
Emeric Brun46591952012-05-18 15:47:34 +02001389 goto read0;
1390 }
1391 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001392 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001393 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001394 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001395 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001396 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001397 break;
1398 }
1399 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001400 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1401 /* handshake is running, and it may need to re-enable read */
1402 conn->flags |= CO_FL_SSL_WAIT_HS;
1403 __conn_sock_want_recv(conn);
1404 break;
1405 }
Emeric Brun46591952012-05-18 15:47:34 +02001406 /* we need to poll for retry a read later */
1407 __conn_data_poll_recv(conn);
1408 break;
1409 }
1410 /* otherwise it's a real error */
1411 goto out_error;
1412 }
1413 }
1414 return done;
1415
1416 read0:
1417 conn_sock_read0(conn);
1418 return done;
1419 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001420 /* Clear openssl global errors stack */
1421 ERR_clear_error();
1422
Emeric Brun46591952012-05-18 15:47:34 +02001423 conn->flags |= CO_FL_ERROR;
1424 return done;
1425}
1426
1427
1428/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1429 * <flags> may contain MSG_MORE to make the system hold on without sending
1430 * data too fast, but this flag is ignored at the moment.
1431 * Only one call to send() is performed, unless the buffer wraps, in which case
1432 * a second call may be performed. The connection's flags are updated with
1433 * whatever special event is detected (error, empty). The caller is responsible
1434 * for taking care of those events and avoiding the call if inappropriate. The
1435 * function does not call the connection's polling update function, so the caller
1436 * is responsible for this.
1437 */
1438static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1439{
1440 int ret, try, done;
1441
1442 done = 0;
1443
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001444 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001445 goto out_error;
1446
1447 if (conn->flags & CO_FL_HANDSHAKE)
1448 /* a handshake was requested */
1449 return 0;
1450
1451 /* send the largest possible block. For this we perform only one call
1452 * to send() unless the buffer wraps and we exactly fill the first hunk,
1453 * in which case we accept to do it once again.
1454 */
1455 while (buf->o) {
Kevin Hestercad82342013-05-30 15:12:41 -07001456 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01001457
1458 if (global.tune.ssl_max_record && try > global.tune.ssl_max_record)
1459 try = global.tune.ssl_max_record;
1460
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001461 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001462 if (conn->flags & CO_FL_ERROR) {
1463 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001464 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001465 }
Emeric Brun46591952012-05-18 15:47:34 +02001466 if (ret > 0) {
1467 buf->o -= ret;
1468 done += ret;
1469
Willy Tarreau5fb38032012-12-16 19:39:09 +01001470 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001471 /* optimize data alignment in the buffer */
1472 buf->p = buf->data;
1473
1474 /* if the system buffer is full, don't insist */
1475 if (ret < try)
1476 break;
1477 }
1478 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001479 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001480 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001481 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1482 /* handshake is running, and it may need to re-enable write */
1483 conn->flags |= CO_FL_SSL_WAIT_HS;
1484 __conn_sock_want_send(conn);
1485 break;
1486 }
Emeric Brun46591952012-05-18 15:47:34 +02001487 /* we need to poll to retry a write later */
1488 __conn_data_poll_send(conn);
1489 break;
1490 }
1491 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001492 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001493 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001494 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001495 break;
1496 }
1497 goto out_error;
1498 }
1499 }
1500 return done;
1501
1502 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001503 /* Clear openssl global errors stack */
1504 ERR_clear_error();
1505
Emeric Brun46591952012-05-18 15:47:34 +02001506 conn->flags |= CO_FL_ERROR;
1507 return done;
1508}
1509
Emeric Brun46591952012-05-18 15:47:34 +02001510static void ssl_sock_close(struct connection *conn) {
1511
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001512 if (conn->xprt_ctx) {
1513 SSL_free(conn->xprt_ctx);
1514 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001515 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001516 }
Emeric Brun46591952012-05-18 15:47:34 +02001517}
1518
1519/* This function tries to perform a clean shutdown on an SSL connection, and in
1520 * any case, flags the connection as reusable if no handshake was in progress.
1521 */
1522static void ssl_sock_shutw(struct connection *conn, int clean)
1523{
1524 if (conn->flags & CO_FL_HANDSHAKE)
1525 return;
1526 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001527 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1528 /* Clear openssl global errors stack */
1529 ERR_clear_error();
1530 }
Emeric Brun46591952012-05-18 15:47:34 +02001531
1532 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001533 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001534}
1535
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001536/* used for logging, may be changed for a sample fetch later */
1537const char *ssl_sock_get_cipher_name(struct connection *conn)
1538{
1539 if (!conn->xprt && !conn->xprt_ctx)
1540 return NULL;
1541 return SSL_get_cipher_name(conn->xprt_ctx);
1542}
1543
1544/* used for logging, may be changed for a sample fetch later */
1545const char *ssl_sock_get_proto_version(struct connection *conn)
1546{
1547 if (!conn->xprt && !conn->xprt_ctx)
1548 return NULL;
1549 return SSL_get_version(conn->xprt_ctx);
1550}
1551
Willy Tarreau8d598402012-10-22 17:58:39 +02001552/* Extract a serial from a cert, and copy it to a chunk.
1553 * Returns 1 if serial is found and copied, 0 if no serial found and
1554 * -1 if output is not large enough.
1555 */
1556static int
1557ssl_sock_get_serial(X509 *crt, struct chunk *out)
1558{
1559 ASN1_INTEGER *serial;
1560
1561 serial = X509_get_serialNumber(crt);
1562 if (!serial)
1563 return 0;
1564
1565 if (out->size < serial->length)
1566 return -1;
1567
1568 memcpy(out->str, serial->data, serial->length);
1569 out->len = serial->length;
1570 return 1;
1571}
1572
Emeric Brunce5ad802012-10-22 14:11:22 +02001573
1574/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1575 * Returns 1 if serial is found and copied, 0 if no valid time found
1576 * and -1 if output is not large enough.
1577 */
1578static int
1579ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1580{
1581 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1582 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1583
1584 if (gentm->length < 12)
1585 return 0;
1586 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1587 return 0;
1588 if (out->size < gentm->length-2)
1589 return -1;
1590
1591 memcpy(out->str, gentm->data+2, gentm->length-2);
1592 out->len = gentm->length-2;
1593 return 1;
1594 }
1595 else if (tm->type == V_ASN1_UTCTIME) {
1596 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1597
1598 if (utctm->length < 10)
1599 return 0;
1600 if (utctm->data[0] >= 0x35)
1601 return 0;
1602 if (out->size < utctm->length)
1603 return -1;
1604
1605 memcpy(out->str, utctm->data, utctm->length);
1606 out->len = utctm->length;
1607 return 1;
1608 }
1609
1610 return 0;
1611}
1612
Emeric Brun87855892012-10-17 17:39:35 +02001613/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1614 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1615 */
1616static int
1617ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1618{
1619 X509_NAME_ENTRY *ne;
1620 int i, j, n;
1621 int cur = 0;
1622 const char *s;
1623 char tmp[128];
1624
1625 out->len = 0;
1626 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1627 if (pos < 0)
1628 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1629 else
1630 j = i;
1631
1632 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1633 n = OBJ_obj2nid(ne->object);
1634 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1635 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1636 s = tmp;
1637 }
1638
1639 if (chunk_strcasecmp(entry, s) != 0)
1640 continue;
1641
1642 if (pos < 0)
1643 cur--;
1644 else
1645 cur++;
1646
1647 if (cur != pos)
1648 continue;
1649
1650 if (ne->value->length > out->size)
1651 return -1;
1652
1653 memcpy(out->str, ne->value->data, ne->value->length);
1654 out->len = ne->value->length;
1655 return 1;
1656 }
1657
1658 return 0;
1659
1660}
1661
1662/* Extract and format full DN from a X509_NAME and copy result into a chunk
1663 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1664 */
1665static int
1666ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1667{
1668 X509_NAME_ENTRY *ne;
1669 int i, n, ln;
1670 int l = 0;
1671 const char *s;
1672 char *p;
1673 char tmp[128];
1674
1675 out->len = 0;
1676 p = out->str;
1677 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1678 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1679 n = OBJ_obj2nid(ne->object);
1680 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1681 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1682 s = tmp;
1683 }
1684 ln = strlen(s);
1685
1686 l += 1 + ln + 1 + ne->value->length;
1687 if (l > out->size)
1688 return -1;
1689 out->len = l;
1690
1691 *(p++)='/';
1692 memcpy(p, s, ln);
1693 p += ln;
1694 *(p++)='=';
1695 memcpy(p, ne->value->data, ne->value->length);
1696 p += ne->value->length;
1697 }
1698
1699 if (!out->len)
1700 return 0;
1701
1702 return 1;
1703}
1704
Willy Tarreau7875d092012-09-10 08:20:03 +02001705/***** Below are some sample fetching functions for ACL/patterns *****/
1706
Emeric Brune64aef12012-09-21 13:15:06 +02001707/* boolean, returns true if client cert was present */
1708static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001709smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001710 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brune64aef12012-09-21 13:15:06 +02001711{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001712 struct connection *conn;
1713
1714 if (!l4)
1715 return 0;
1716
1717 conn = objt_conn(l4->si[0].end);
1718 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001719 return 0;
1720
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001721 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001722 smp->flags |= SMP_F_MAY_CHANGE;
1723 return 0;
1724 }
1725
1726 smp->flags = 0;
1727 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001728 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001729
1730 return 1;
1731}
1732
Willy Tarreau8d598402012-10-22 17:58:39 +02001733/* bin, returns serial in a binary chunk */
1734static int
1735smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001736 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02001737{
1738 X509 *crt = NULL;
1739 int ret = 0;
1740 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001741 struct connection *conn;
1742
1743 if (!l4)
1744 return 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02001745
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001746 conn = objt_conn(l4->si[0].end);
1747 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001748 return 0;
1749
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001750 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001751 smp->flags |= SMP_F_MAY_CHANGE;
1752 return 0;
1753 }
1754
1755 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001756 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001757 if (!crt)
1758 goto out;
1759
Willy Tarreau47ca5452012-12-23 20:22:19 +01001760 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001761 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1762 goto out;
1763
1764 smp->data.str = *smp_trash;
1765 smp->type = SMP_T_BIN;
1766 ret = 1;
1767out:
1768 if (crt)
1769 X509_free(crt);
1770 return ret;
1771}
Emeric Brune64aef12012-09-21 13:15:06 +02001772
James Votha051b4a2013-05-14 20:37:59 +02001773/* bin, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk */
1774static int
1775smp_fetch_ssl_c_sha1(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001776 const struct arg *args, struct sample *smp, const char *kw)
James Votha051b4a2013-05-14 20:37:59 +02001777{
1778 X509 *crt = NULL;
1779 const EVP_MD *digest;
1780 int ret = 0;
1781 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001782 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02001783
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001784 if (!l4)
James Votha051b4a2013-05-14 20:37:59 +02001785 return 0;
1786
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001787 conn = objt_conn(l4->si[0].end);
1788 if (!conn || conn->xprt != &ssl_sock)
1789 return 0;
1790
1791 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02001792 smp->flags |= SMP_F_MAY_CHANGE;
1793 return 0;
1794 }
1795
1796 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001797 crt = SSL_get_peer_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02001798 if (!crt)
1799 goto out;
1800
1801 smp_trash = get_trash_chunk();
1802 digest = EVP_sha1();
1803 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
1804
1805 smp->data.str = *smp_trash;
1806 smp->type = SMP_T_BIN;
1807 ret = 1;
1808out:
1809 if (crt)
1810 X509_free(crt);
1811 return ret;
1812}
1813
Emeric Brunce5ad802012-10-22 14:11:22 +02001814/*str, returns notafter date in ASN1_UTCTIME format */
1815static int
1816smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001817 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001818{
1819 X509 *crt = NULL;
1820 int ret = 0;
1821 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001822 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02001823
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001824 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02001825 return 0;
1826
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001827 conn = objt_conn(l4->si[0].end);
1828 if (!conn || conn->xprt != &ssl_sock)
1829 return 0;
1830
1831 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001832 smp->flags |= SMP_F_MAY_CHANGE;
1833 return 0;
1834 }
1835
1836 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001837 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001838 if (!crt)
1839 goto out;
1840
Willy Tarreau47ca5452012-12-23 20:22:19 +01001841 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001842 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1843 goto out;
1844
1845 smp->data.str = *smp_trash;
1846 smp->type = SMP_T_STR;
1847 ret = 1;
1848out:
1849 if (crt)
1850 X509_free(crt);
1851 return ret;
1852}
1853
Emeric Brun87855892012-10-17 17:39:35 +02001854/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1855static int
1856smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001857 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02001858{
1859 X509 *crt = NULL;
1860 X509_NAME *name;
1861 int ret = 0;
1862 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001863 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02001864
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001865 if (!l4)
Emeric Brun87855892012-10-17 17:39:35 +02001866 return 0;
1867
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001868 conn = objt_conn(l4->si[0].end);
1869 if (!conn || conn->xprt != &ssl_sock)
1870 return 0;
1871
1872 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001873 smp->flags |= SMP_F_MAY_CHANGE;
1874 return 0;
1875 }
1876
1877 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001878 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001879 if (!crt)
1880 goto out;
1881
1882 name = X509_get_issuer_name(crt);
1883 if (!name)
1884 goto out;
1885
Willy Tarreau47ca5452012-12-23 20:22:19 +01001886 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001887 if (args && args[0].type == ARGT_STR) {
1888 int pos = 1;
1889
1890 if (args[1].type == ARGT_SINT)
1891 pos = args[1].data.sint;
1892 else if (args[1].type == ARGT_UINT)
1893 pos =(int)args[1].data.uint;
1894
1895 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1896 goto out;
1897 }
1898 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1899 goto out;
1900
1901 smp->type = SMP_T_STR;
1902 smp->data.str = *smp_trash;
1903 ret = 1;
1904out:
1905 if (crt)
1906 X509_free(crt);
1907 return ret;
1908}
1909
Emeric Brunce5ad802012-10-22 14:11:22 +02001910/*str, returns notbefore date in ASN1_UTCTIME format */
1911static int
1912smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001913 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001914{
1915 X509 *crt = NULL;
1916 int ret = 0;
1917 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001918 struct connection *conn;
1919
1920 if (!l4)
1921 return 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02001922
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001923 conn = objt_conn(l4->si[0].end);
1924 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001925 return 0;
1926
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001927 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001928 smp->flags |= SMP_F_MAY_CHANGE;
1929 return 0;
1930 }
1931
1932 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001933 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001934 if (!crt)
1935 goto out;
1936
Willy Tarreau47ca5452012-12-23 20:22:19 +01001937 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001938 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1939 goto out;
1940
1941 smp->data.str = *smp_trash;
1942 smp->type = SMP_T_STR;
1943 ret = 1;
1944out:
1945 if (crt)
1946 X509_free(crt);
1947 return ret;
1948}
1949
Emeric Brun87855892012-10-17 17:39:35 +02001950/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1951static int
1952smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001953 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02001954{
1955 X509 *crt = NULL;
1956 X509_NAME *name;
1957 int ret = 0;
1958 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001959 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02001960
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001961 if (!l4)
Emeric Brun87855892012-10-17 17:39:35 +02001962 return 0;
1963
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001964 conn = objt_conn(l4->si[0].end);
1965 if (!conn || conn->xprt != &ssl_sock)
1966 return 0;
1967
1968 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001969 smp->flags |= SMP_F_MAY_CHANGE;
1970 return 0;
1971 }
1972
1973 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001974 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001975 if (!crt)
1976 goto out;
1977
1978 name = X509_get_subject_name(crt);
1979 if (!name)
1980 goto out;
1981
Willy Tarreau47ca5452012-12-23 20:22:19 +01001982 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001983 if (args && args[0].type == ARGT_STR) {
1984 int pos = 1;
1985
1986 if (args[1].type == ARGT_SINT)
1987 pos = args[1].data.sint;
1988 else if (args[1].type == ARGT_UINT)
1989 pos =(int)args[1].data.uint;
1990
1991 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1992 goto out;
1993 }
1994 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1995 goto out;
1996
1997 smp->type = SMP_T_STR;
1998 smp->data.str = *smp_trash;
1999 ret = 1;
2000out:
2001 if (crt)
2002 X509_free(crt);
2003 return ret;
2004}
Emeric Brun9143d372012-12-20 15:44:16 +01002005
2006/* integer, returns true if current session use a client certificate */
2007static int
2008smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002009 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun9143d372012-12-20 15:44:16 +01002010{
2011 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002012 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01002013
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002014 if (!l4)
Emeric Brun9143d372012-12-20 15:44:16 +01002015 return 0;
2016
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002017 conn = objt_conn(l4->si[0].end);
2018 if (!conn || conn->xprt != &ssl_sock)
2019 return 0;
2020
2021 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01002022 smp->flags |= SMP_F_MAY_CHANGE;
2023 return 0;
2024 }
2025
2026 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002027 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01002028 if (crt) {
2029 X509_free(crt);
2030 }
2031
2032 smp->type = SMP_T_BOOL;
2033 smp->data.uint = (crt != NULL);
2034 return 1;
2035}
2036
Emeric Bruna7359fd2012-10-17 15:03:11 +02002037/* integer, returns the client certificate version */
2038static int
2039smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002040 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002041{
2042 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002043 struct connection *conn;
2044
2045 if (!l4)
2046 return 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02002047
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002048 conn = objt_conn(l4->si[0].end);
2049 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002050 return 0;
2051
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002052 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002053 smp->flags |= SMP_F_MAY_CHANGE;
2054 return 0;
2055 }
2056
2057 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002058 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002059 if (!crt)
2060 return 0;
2061
2062 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2063 X509_free(crt);
2064 smp->type = SMP_T_UINT;
2065
2066 return 1;
2067}
2068
Emeric Brun7f56e742012-10-19 18:15:40 +02002069/* str, returns the client certificate sig alg */
2070static int
2071smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002072 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002073{
2074 X509 *crt;
2075 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002076 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02002077
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002078 if (!l4)
Emeric Brun7f56e742012-10-19 18:15:40 +02002079 return 0;
2080
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002081 conn = objt_conn(l4->si[0].end);
2082 if (!conn || conn->xprt != &ssl_sock)
2083 return 0;
2084
2085 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002086 smp->flags |= SMP_F_MAY_CHANGE;
2087 return 0;
2088 }
2089
2090 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002091 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002092 if (!crt)
2093 return 0;
2094
2095 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2096
2097 smp->data.str.str = (char *)OBJ_nid2sn(nid);
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002098 if (!smp->data.str.str) {
2099 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02002100 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002101 }
Emeric Brun7f56e742012-10-19 18:15:40 +02002102
2103 smp->type = SMP_T_CSTR;
2104 smp->data.str.len = strlen(smp->data.str.str);
2105 X509_free(crt);
2106
2107 return 1;
2108}
2109
Emeric Brun521a0112012-10-22 12:22:55 +02002110/* str, returns the client certificate key alg */
2111static int
2112smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002113 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002114{
2115 X509 *crt;
2116 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002117 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02002118
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002119 if (!l4)
Emeric Brun521a0112012-10-22 12:22:55 +02002120 return 0;
2121
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002122 conn = objt_conn(l4->si[0].end);
2123 if (!conn || conn->xprt != &ssl_sock)
2124 return 0;
2125
2126 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002127 smp->flags |= SMP_F_MAY_CHANGE;
2128 return 0;
2129 }
2130
2131 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002132 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002133 if (!crt)
2134 return 0;
2135
2136 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2137
2138 smp->data.str.str = (char *)OBJ_nid2sn(nid);
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002139 if (!smp->data.str.str) {
2140 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02002141 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002142 }
Emeric Brun521a0112012-10-22 12:22:55 +02002143
2144 smp->type = SMP_T_CSTR;
2145 smp->data.str.len = strlen(smp->data.str.str);
2146 X509_free(crt);
2147
2148 return 1;
2149}
2150
Emeric Brun2525b6b2012-10-18 15:59:43 +02002151/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02002152static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002153smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002154 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002155{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002156 struct connection *conn = objt_conn(l4->si[0].end);
2157
Willy Tarreau7875d092012-09-10 08:20:03 +02002158 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002159 smp->data.uint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02002160 return 1;
2161}
2162
Emeric Brun2525b6b2012-10-18 15:59:43 +02002163/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02002164static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002165smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002166 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002167{
2168#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002169 struct connection *conn = objt_conn(l4->si[0].end);
2170
Willy Tarreau7875d092012-09-10 08:20:03 +02002171 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002172 smp->data.uint = (conn && conn->xprt == &ssl_sock) &&
2173 conn->xprt_ctx &&
2174 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02002175 return 1;
2176#else
2177 return 0;
2178#endif
2179}
2180
Willy Tarreau8d598402012-10-22 17:58:39 +02002181/* bin, returns serial in a binary chunk */
2182static int
2183smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002184 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02002185{
2186 X509 *crt = NULL;
2187 int ret = 0;
2188 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002189 struct connection *conn;
2190
2191 if (!l4)
2192 return 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02002193
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002194 conn = objt_conn(l4->si[0].end);
2195 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02002196 return 0;
2197
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002198 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02002199 smp->flags |= SMP_F_MAY_CHANGE;
2200 return 0;
2201 }
2202
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002203 crt = SSL_get_certificate(conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02002204 if (!crt)
2205 goto out;
2206
Willy Tarreau47ca5452012-12-23 20:22:19 +01002207 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02002208 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
2209 goto out;
2210
2211 smp->data.str = *smp_trash;
2212 smp->type = SMP_T_BIN;
2213 ret = 1;
2214out:
2215 return ret;
2216}
Emeric Brunce5ad802012-10-22 14:11:22 +02002217/*str, returns notafter date in ASN1_UTCTIME format */
2218static int
2219smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002220 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002221{
2222 X509 *crt = NULL;
2223 int ret = 0;
2224 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002225 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02002226
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002227 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02002228 return 0;
2229
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002230 conn = objt_conn(l4->si[0].end);
2231 if (!conn || conn->xprt != &ssl_sock)
2232 return 0;
2233
2234 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002235 smp->flags |= SMP_F_MAY_CHANGE;
2236 return 0;
2237 }
2238
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002239 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002240 if (!crt)
2241 goto out;
2242
Willy Tarreau47ca5452012-12-23 20:22:19 +01002243 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002244 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
2245 goto out;
2246
2247 smp->data.str = *smp_trash;
2248 smp->type = SMP_T_STR;
2249 ret = 1;
2250out:
2251 return ret;
2252}
2253
2254/*str, returns notbefore date in ASN1_UTCTIME format */
2255static int
2256smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002257 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002258{
2259 X509 *crt = NULL;
2260 int ret = 0;
2261 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002262 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02002263
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002264 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02002265 return 0;
2266
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002267 conn = objt_conn(l4->si[0].end);
2268 if (!conn || conn->xprt != &ssl_sock)
2269 return 0;
2270
2271 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002272 smp->flags |= SMP_F_MAY_CHANGE;
2273 return 0;
2274 }
2275
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002276 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002277 if (!crt)
2278 goto out;
2279
Willy Tarreau47ca5452012-12-23 20:22:19 +01002280 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002281 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
2282 goto out;
2283
2284 smp->data.str = *smp_trash;
2285 smp->type = SMP_T_STR;
2286 ret = 1;
2287out:
2288 return ret;
2289}
Willy Tarreau8d598402012-10-22 17:58:39 +02002290
Emeric Bruna7359fd2012-10-17 15:03:11 +02002291/* integer, returns the frontend certificate version */
2292static int
2293smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002294 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002295{
2296 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002297 struct connection *conn;
Emeric Bruna7359fd2012-10-17 15:03:11 +02002298
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002299 if (!l4)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002300 return 0;
2301
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002302 conn = objt_conn(l4->si[0].end);
2303 if (!conn || conn->xprt != &ssl_sock)
2304 return 0;
2305
2306 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002307 smp->flags |= SMP_F_MAY_CHANGE;
2308 return 0;
2309 }
2310
2311 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002312 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002313 if (!crt)
2314 return 0;
2315
2316 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2317 smp->type = SMP_T_UINT;
2318
2319 return 1;
2320}
2321
Emeric Brun7f56e742012-10-19 18:15:40 +02002322/* str, returns the client certificate sig alg */
2323static int
2324smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002325 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002326{
2327 X509 *crt;
2328 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002329 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02002330
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002331 if (!l4)
Emeric Brun7f56e742012-10-19 18:15:40 +02002332 return 0;
2333
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002334 conn = objt_conn(l4->si[0].end);
2335 if (!conn || conn->xprt != &ssl_sock)
2336 return 0;
2337
2338 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002339 smp->flags |= SMP_F_MAY_CHANGE;
2340 return 0;
2341 }
2342
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002343 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002344 if (!crt)
2345 return 0;
2346
2347 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2348
2349 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2350 if (!smp->data.str.str)
2351 return 0;
2352
2353 smp->type = SMP_T_CSTR;
2354 smp->data.str.len = strlen(smp->data.str.str);
2355
2356 return 1;
2357}
2358
Emeric Brun521a0112012-10-22 12:22:55 +02002359/* str, returns the client certificate key alg */
2360static int
2361smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002362 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002363{
2364 X509 *crt;
2365 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002366 struct connection *conn;
2367
2368 if (!l4)
2369 return 0;
Emeric Brun521a0112012-10-22 12:22:55 +02002370
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002371 conn = objt_conn(l4->si[0].end);
2372 if (!conn || conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002373 return 0;
2374
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002375 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002376 smp->flags |= SMP_F_MAY_CHANGE;
2377 return 0;
2378 }
2379
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002380 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002381 if (!crt)
2382 return 0;
2383
2384 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2385
2386 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2387 if (!smp->data.str.str)
2388 return 0;
2389
2390 smp->type = SMP_T_CSTR;
2391 smp->data.str.len = strlen(smp->data.str.str);
2392
2393 return 1;
2394}
2395
Emeric Brun87855892012-10-17 17:39:35 +02002396/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2397static int
2398smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002399 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002400{
2401 X509 *crt = NULL;
2402 X509_NAME *name;
2403 int ret = 0;
2404 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002405 struct connection *conn;
2406
2407 if (!l4)
2408 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02002409
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002410 conn = objt_conn(l4->si[0].end);
2411 if (!conn || conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002412 return 0;
2413
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002414 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002415 smp->flags |= SMP_F_MAY_CHANGE;
2416 return 0;
2417 }
2418
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002419 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002420 if (!crt)
2421 goto out;
2422
2423 name = X509_get_issuer_name(crt);
2424 if (!name)
2425 goto out;
2426
Willy Tarreau47ca5452012-12-23 20:22:19 +01002427 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002428 if (args && args[0].type == ARGT_STR) {
2429 int pos = 1;
2430
2431 if (args[1].type == ARGT_SINT)
2432 pos = args[1].data.sint;
2433 else if (args[1].type == ARGT_UINT)
2434 pos =(int)args[1].data.uint;
2435
2436 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2437 goto out;
2438 }
2439 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2440 goto out;
2441
2442 smp->type = SMP_T_STR;
2443 smp->data.str = *smp_trash;
2444 ret = 1;
2445out:
2446 return ret;
2447}
2448
2449/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2450static int
2451smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002452 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002453{
2454 X509 *crt = NULL;
2455 X509_NAME *name;
2456 int ret = 0;
2457 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002458 struct connection *conn;
2459
2460 if (!l4)
2461 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02002462
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002463 conn = objt_conn(l4->si[0].end);
2464 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002465 return 0;
2466
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002467 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002468 smp->flags |= SMP_F_MAY_CHANGE;
2469 return 0;
2470 }
2471
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002472 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002473 if (!crt)
2474 goto out;
2475
2476 name = X509_get_subject_name(crt);
2477 if (!name)
2478 goto out;
2479
Willy Tarreau47ca5452012-12-23 20:22:19 +01002480 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002481 if (args && args[0].type == ARGT_STR) {
2482 int pos = 1;
2483
2484 if (args[1].type == ARGT_SINT)
2485 pos = args[1].data.sint;
2486 else if (args[1].type == ARGT_UINT)
2487 pos =(int)args[1].data.uint;
2488
2489 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2490 goto out;
2491 }
2492 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2493 goto out;
2494
2495 smp->type = SMP_T_STR;
2496 smp->data.str = *smp_trash;
2497 ret = 1;
2498out:
2499 return ret;
2500}
2501
Emeric Brun589fcad2012-10-16 14:13:26 +02002502static int
2503smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002504 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002505{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002506 struct connection *conn;
2507
Emeric Brun589fcad2012-10-16 14:13:26 +02002508 smp->flags = 0;
2509
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002510 if (!l4)
2511 return 0;
2512
2513 conn = objt_conn(l4->si[0].end);
2514 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002515 return 0;
2516
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002517 smp->data.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002518 if (!smp->data.str.str)
2519 return 0;
2520
2521 smp->type = SMP_T_CSTR;
2522 smp->data.str.len = strlen(smp->data.str.str);
2523
2524 return 1;
2525}
2526
2527static int
2528smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002529 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002530{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002531 struct connection *conn;
2532
Emeric Brun589fcad2012-10-16 14:13:26 +02002533 smp->flags = 0;
2534
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002535 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002536 return 0;
2537
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002538 conn = objt_conn(l4->si[0].end);
2539 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002540 return 0;
2541
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002542 if (!SSL_get_cipher_bits(conn->xprt_ctx, (int *)&smp->data.uint))
2543 return 0;
2544
Emeric Brun589fcad2012-10-16 14:13:26 +02002545 smp->type = SMP_T_UINT;
2546
2547 return 1;
2548}
2549
2550static int
2551smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002552 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002553{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002554 struct connection *conn;
2555
Emeric Brun589fcad2012-10-16 14:13:26 +02002556 smp->flags = 0;
2557
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002558 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002559 return 0;
2560
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002561 conn = objt_conn(l4->si[0].end);
2562 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2563 return 0;
2564
2565 smp->data.uint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002566 if (!smp->data.uint)
2567 return 0;
2568
2569 smp->type = SMP_T_UINT;
2570
2571 return 1;
2572}
2573
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002574#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002575static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002576smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002577 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002578{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002579 struct connection *conn;
2580
Willy Tarreaua33c6542012-10-15 13:19:06 +02002581 smp->flags = 0;
2582 smp->type = SMP_T_CSTR;
2583
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002584 if (!l4)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002585 return 0;
2586
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002587 conn = objt_conn(l4->si[0].end);
2588 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2589 return 0;
2590
Willy Tarreaua33c6542012-10-15 13:19:06 +02002591 smp->data.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002592 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002593 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2594
2595 if (!smp->data.str.str)
2596 return 0;
2597
2598 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002599}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002600#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002601
Willy Tarreauab861d32013-04-02 02:30:41 +02002602#ifdef OPENSSL_ALPN_NEGOTIATED
2603static int
2604smp_fetch_ssl_fc_alpn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002605 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreauab861d32013-04-02 02:30:41 +02002606{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002607 struct connection *conn;
2608
Willy Tarreauab861d32013-04-02 02:30:41 +02002609 smp->flags = 0;
2610 smp->type = SMP_T_CSTR;
2611
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002612 if (!l4)
2613 return 0;
2614
2615 conn = objt_conn(l4->si[0].end);
2616 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02002617 return 0;
2618
2619 smp->data.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002620 SSL_get0_alpn_negotiated(conn->xprt_ctx,
Willy Tarreauab861d32013-04-02 02:30:41 +02002621 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2622
2623 if (!smp->data.str.str)
2624 return 0;
2625
2626 return 1;
2627}
2628#endif
2629
Willy Tarreaua33c6542012-10-15 13:19:06 +02002630static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002631smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002632 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002633{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002634 struct connection *conn;
2635
Emeric Brun589fcad2012-10-16 14:13:26 +02002636 smp->flags = 0;
2637
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002638 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002639 return 0;
2640
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002641 conn = objt_conn(l4->si[0].end);
2642 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2643 return 0;
2644
2645 smp->data.str.str = (char *)SSL_get_version(conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002646 if (!smp->data.str.str)
2647 return 0;
2648
2649 smp->type = SMP_T_CSTR;
2650 smp->data.str.len = strlen(smp->data.str.str);
2651
2652 return 1;
2653}
2654
2655static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002656smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002657 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunfe68f682012-10-16 14:59:28 +02002658{
2659#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2660 SSL_SESSION *sess;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002661 struct connection *conn;
Emeric Brunfe68f682012-10-16 14:59:28 +02002662
2663 smp->flags = 0;
2664 smp->type = SMP_T_CBIN;
2665
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002666 if (!l4)
Emeric Brunfe68f682012-10-16 14:59:28 +02002667 return 0;
2668
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002669 conn = objt_conn(l4->si[0].end);
2670 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2671 return 0;
2672
2673 sess = SSL_get_session(conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002674 if (!sess)
2675 return 0;
2676
2677 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2678 if (!smp->data.str.str || !&smp->data.str.len)
2679 return 0;
2680
2681 return 1;
2682#else
2683 return 0;
2684#endif
2685}
2686
2687static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002688smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002689 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002690{
2691#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002692 struct connection *conn;
2693
Willy Tarreau7875d092012-09-10 08:20:03 +02002694 smp->flags = 0;
2695 smp->type = SMP_T_CSTR;
2696
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002697 if (!l4)
Willy Tarreau7875d092012-09-10 08:20:03 +02002698 return 0;
2699
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002700 conn = objt_conn(l4->si[0].end);
2701 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2702 return 0;
2703
2704 smp->data.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau3e394c92012-09-14 23:56:58 +02002705 if (!smp->data.str.str)
2706 return 0;
2707
Willy Tarreau7875d092012-09-10 08:20:03 +02002708 smp->data.str.len = strlen(smp->data.str.str);
2709 return 1;
2710#else
2711 return 0;
2712#endif
2713}
2714
Emeric Brun2525b6b2012-10-18 15:59:43 +02002715/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002716static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002717smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002718 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002719{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002720 struct connection *conn;
2721
2722 if (!l4)
Emeric Brunf282a812012-09-21 15:27:54 +02002723 return 0;
2724
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002725 conn = objt_conn(l4->si[0].end);
2726 if (!conn || conn->xprt != &ssl_sock)
2727 return 0;
2728
2729 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002730 smp->flags = SMP_F_MAY_CHANGE;
2731 return 0;
2732 }
2733
2734 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002735 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002736 smp->flags = 0;
2737
2738 return 1;
2739}
2740
Emeric Brun2525b6b2012-10-18 15:59:43 +02002741/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002742static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002743smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002744 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002745{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002746 struct connection *conn;
2747
2748 if (!l4)
2749 return 0;
2750
2751 conn = objt_conn(l4->si[0].end);
2752 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002753 return 0;
2754
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002755 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002756 smp->flags = SMP_F_MAY_CHANGE;
2757 return 0;
2758 }
2759
2760 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002761 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002762 smp->flags = 0;
2763
2764 return 1;
2765}
2766
Emeric Brun2525b6b2012-10-18 15:59:43 +02002767/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002768static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002769smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002770 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002771{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002772 struct connection *conn;
2773
2774 if (!l4)
Emeric Brunf282a812012-09-21 15:27:54 +02002775 return 0;
2776
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002777 conn = objt_conn(l4->si[0].end);
2778 if (!conn || conn->xprt != &ssl_sock)
2779 return 0;
2780
2781 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002782 smp->flags = SMP_F_MAY_CHANGE;
2783 return 0;
2784 }
2785
2786 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002787 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002788 smp->flags = 0;
2789
2790 return 1;
2791}
2792
Emeric Brun2525b6b2012-10-18 15:59:43 +02002793/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002794static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002795smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002796 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002797{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002798 struct connection *conn;
2799
2800 if (!l4)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002801 return 0;
2802
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002803 conn = objt_conn(l4->si[0].end);
2804 if (!conn || conn->xprt != &ssl_sock)
2805 return 0;
2806
2807 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002808 smp->flags = SMP_F_MAY_CHANGE;
2809 return 0;
2810 }
2811
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002812 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002813 return 0;
2814
2815 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002816 smp->data.uint = (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002817 smp->flags = 0;
2818
2819 return 1;
2820}
2821
Emeric Brunfb510ea2012-10-05 12:00:26 +02002822/* parse the "ca-file" bind keyword */
2823static 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 +02002824{
2825 if (!*args[cur_arg + 1]) {
2826 if (err)
2827 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2828 return ERR_ALERT | ERR_FATAL;
2829 }
2830
Emeric Brunef42d922012-10-11 16:11:36 +02002831 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2832 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2833 else
2834 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002835
Emeric Brund94b3fe2012-09-20 18:23:56 +02002836 return 0;
2837}
2838
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002839/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002840static 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 +02002841{
2842 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002843 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002844 return ERR_ALERT | ERR_FATAL;
2845 }
2846
Emeric Brun76d88952012-10-05 15:47:31 +02002847 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002848 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002849 return 0;
2850}
2851
2852/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002853static 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 +02002854{
Willy Tarreau38011032013-08-13 16:59:39 +02002855 char path[MAXPATHLEN];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002856 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002857 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002858 return ERR_ALERT | ERR_FATAL;
2859 }
2860
Emeric Brunc8e8d122012-10-02 18:42:10 +02002861 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
Willy Tarreau38011032013-08-13 16:59:39 +02002862 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02002863 memprintf(err, "'%s' : path too long", args[cur_arg]);
2864 return ERR_ALERT | ERR_FATAL;
2865 }
2866 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2867 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2868 return ERR_ALERT | ERR_FATAL;
2869
2870 return 0;
2871 }
2872
Willy Tarreau4348fad2012-09-20 16:48:07 +02002873 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002874 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002875
2876 return 0;
2877}
2878
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002879/* parse the "crt-list" bind keyword */
2880static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2881{
2882 if (!*args[cur_arg + 1]) {
2883 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
2884 return ERR_ALERT | ERR_FATAL;
2885 }
2886
Willy Tarreauad1731d2013-04-02 17:35:58 +02002887 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
2888 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002889 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02002890 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002891
2892 return 0;
2893}
2894
Emeric Brunfb510ea2012-10-05 12:00:26 +02002895/* parse the "crl-file" bind keyword */
2896static 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 +02002897{
Emeric Brun051cdab2012-10-02 19:25:50 +02002898#ifndef X509_V_FLAG_CRL_CHECK
2899 if (err)
2900 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2901 return ERR_ALERT | ERR_FATAL;
2902#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002903 if (!*args[cur_arg + 1]) {
2904 if (err)
2905 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2906 return ERR_ALERT | ERR_FATAL;
2907 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002908
Emeric Brunef42d922012-10-11 16:11:36 +02002909 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2910 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2911 else
2912 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002913
Emeric Brun2b58d042012-09-20 17:10:03 +02002914 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002915#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002916}
2917
2918/* parse the "ecdhe" bind keyword keywords */
2919static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2920{
2921#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2922 if (err)
2923 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2924 return ERR_ALERT | ERR_FATAL;
2925#elif defined(OPENSSL_NO_ECDH)
2926 if (err)
2927 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2928 return ERR_ALERT | ERR_FATAL;
2929#else
2930 if (!*args[cur_arg + 1]) {
2931 if (err)
2932 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2933 return ERR_ALERT | ERR_FATAL;
2934 }
2935
2936 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002937
2938 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002939#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002940}
2941
Emeric Brun81c00f02012-09-21 14:31:21 +02002942/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2943static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2944{
2945 int code;
2946 char *p = args[cur_arg + 1];
2947 unsigned long long *ignerr = &conf->crt_ignerr;
2948
2949 if (!*p) {
2950 if (err)
2951 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2952 return ERR_ALERT | ERR_FATAL;
2953 }
2954
2955 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2956 ignerr = &conf->ca_ignerr;
2957
2958 if (strcmp(p, "all") == 0) {
2959 *ignerr = ~0ULL;
2960 return 0;
2961 }
2962
2963 while (p) {
2964 code = atoi(p);
2965 if ((code <= 0) || (code > 63)) {
2966 if (err)
2967 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2968 args[cur_arg], code, args[cur_arg + 1]);
2969 return ERR_ALERT | ERR_FATAL;
2970 }
2971 *ignerr |= 1ULL << code;
2972 p = strchr(p, ',');
2973 if (p)
2974 p++;
2975 }
2976
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002977 return 0;
2978}
2979
2980/* parse the "force-sslv3" bind keyword */
2981static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2982{
2983 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2984 return 0;
2985}
2986
2987/* parse the "force-tlsv10" bind keyword */
2988static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2989{
2990 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002991 return 0;
2992}
2993
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002994/* parse the "force-tlsv11" bind keyword */
2995static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2996{
2997#if SSL_OP_NO_TLSv1_1
2998 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
2999 return 0;
3000#else
3001 if (err)
3002 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
3003 return ERR_ALERT | ERR_FATAL;
3004#endif
3005}
3006
3007/* parse the "force-tlsv12" bind keyword */
3008static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3009{
3010#if SSL_OP_NO_TLSv1_2
3011 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
3012 return 0;
3013#else
3014 if (err)
3015 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
3016 return ERR_ALERT | ERR_FATAL;
3017#endif
3018}
3019
3020
Emeric Brun2d0c4822012-10-02 13:45:20 +02003021/* parse the "no-tls-tickets" bind keyword */
3022static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3023{
Emeric Brun89675492012-10-05 13:48:26 +02003024 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02003025 return 0;
3026}
3027
Emeric Brun2d0c4822012-10-02 13:45:20 +02003028
Emeric Brun9b3009b2012-10-05 11:55:06 +02003029/* parse the "no-sslv3" bind keyword */
3030static 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 +02003031{
Emeric Brun89675492012-10-05 13:48:26 +02003032 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003033 return 0;
3034}
3035
Emeric Brun9b3009b2012-10-05 11:55:06 +02003036/* parse the "no-tlsv10" bind keyword */
3037static 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 +02003038{
Emeric Brun89675492012-10-05 13:48:26 +02003039 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02003040 return 0;
3041}
3042
Emeric Brun9b3009b2012-10-05 11:55:06 +02003043/* parse the "no-tlsv11" bind keyword */
3044static 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 +02003045{
Emeric Brun89675492012-10-05 13:48:26 +02003046 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02003047 return 0;
3048}
3049
Emeric Brun9b3009b2012-10-05 11:55:06 +02003050/* parse the "no-tlsv12" bind keyword */
3051static 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 +02003052{
Emeric Brun89675492012-10-05 13:48:26 +02003053 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003054 return 0;
3055}
3056
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003057/* parse the "npn" bind keyword */
3058static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3059{
3060#ifdef OPENSSL_NPN_NEGOTIATED
3061 char *p1, *p2;
3062
3063 if (!*args[cur_arg + 1]) {
3064 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
3065 return ERR_ALERT | ERR_FATAL;
3066 }
3067
3068 free(conf->npn_str);
3069
3070 /* the NPN string is built as a suite of (<len> <name>)* */
3071 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
3072 conf->npn_str = calloc(1, conf->npn_len);
3073 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
3074
3075 /* replace commas with the name length */
3076 p1 = conf->npn_str;
3077 p2 = p1 + 1;
3078 while (1) {
3079 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
3080 if (!p2)
3081 p2 = p1 + 1 + strlen(p1 + 1);
3082
3083 if (p2 - (p1 + 1) > 255) {
3084 *p2 = '\0';
3085 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
3086 return ERR_ALERT | ERR_FATAL;
3087 }
3088
3089 *p1 = p2 - (p1 + 1);
3090 p1 = p2;
3091
3092 if (!*p2)
3093 break;
3094
3095 *(p2++) = '\0';
3096 }
3097 return 0;
3098#else
3099 if (err)
3100 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
3101 return ERR_ALERT | ERR_FATAL;
3102#endif
3103}
3104
Willy Tarreauab861d32013-04-02 02:30:41 +02003105/* parse the "alpn" bind keyword */
3106static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3107{
3108#ifdef OPENSSL_ALPN_NEGOTIATED
3109 char *p1, *p2;
3110
3111 if (!*args[cur_arg + 1]) {
3112 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
3113 return ERR_ALERT | ERR_FATAL;
3114 }
3115
3116 free(conf->alpn_str);
3117
3118 /* the ALPN string is built as a suite of (<len> <name>)* */
3119 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
3120 conf->alpn_str = calloc(1, conf->alpn_len);
3121 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
3122
3123 /* replace commas with the name length */
3124 p1 = conf->alpn_str;
3125 p2 = p1 + 1;
3126 while (1) {
3127 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
3128 if (!p2)
3129 p2 = p1 + 1 + strlen(p1 + 1);
3130
3131 if (p2 - (p1 + 1) > 255) {
3132 *p2 = '\0';
3133 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
3134 return ERR_ALERT | ERR_FATAL;
3135 }
3136
3137 *p1 = p2 - (p1 + 1);
3138 p1 = p2;
3139
3140 if (!*p2)
3141 break;
3142
3143 *(p2++) = '\0';
3144 }
3145 return 0;
3146#else
3147 if (err)
3148 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
3149 return ERR_ALERT | ERR_FATAL;
3150#endif
3151}
3152
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003153/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003154static 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 +02003155{
Willy Tarreau81796be2012-09-22 19:11:47 +02003156 struct listener *l;
3157
Willy Tarreau4348fad2012-09-20 16:48:07 +02003158 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02003159
3160 if (global.listen_default_ciphers && !conf->ciphers)
3161 conf->ciphers = strdup(global.listen_default_ciphers);
3162
Willy Tarreau81796be2012-09-22 19:11:47 +02003163 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003164 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02003165
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003166 return 0;
3167}
3168
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003169/* parse the "strict-sni" bind keyword */
3170static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3171{
3172 conf->strict_sni = 1;
3173 return 0;
3174}
3175
Emeric Brund94b3fe2012-09-20 18:23:56 +02003176/* parse the "verify" bind keyword */
3177static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3178{
3179 if (!*args[cur_arg + 1]) {
3180 if (err)
3181 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
3182 return ERR_ALERT | ERR_FATAL;
3183 }
3184
3185 if (strcmp(args[cur_arg + 1], "none") == 0)
3186 conf->verify = SSL_VERIFY_NONE;
3187 else if (strcmp(args[cur_arg + 1], "optional") == 0)
3188 conf->verify = SSL_VERIFY_PEER;
3189 else if (strcmp(args[cur_arg + 1], "required") == 0)
3190 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
3191 else {
3192 if (err)
3193 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
3194 args[cur_arg], args[cur_arg + 1]);
3195 return ERR_ALERT | ERR_FATAL;
3196 }
3197
3198 return 0;
3199}
3200
Willy Tarreau92faadf2012-10-10 23:04:25 +02003201/************** "server" keywords ****************/
3202
Emeric Brunef42d922012-10-11 16:11:36 +02003203/* parse the "ca-file" server keyword */
3204static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3205{
3206 if (!*args[*cur_arg + 1]) {
3207 if (err)
3208 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
3209 return ERR_ALERT | ERR_FATAL;
3210 }
3211
3212 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3213 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3214 else
3215 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
3216
3217 return 0;
3218}
3219
Willy Tarreau92faadf2012-10-10 23:04:25 +02003220/* parse the "check-ssl" server keyword */
3221static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3222{
3223 newsrv->check.use_ssl = 1;
3224 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3225 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3226 return 0;
3227}
3228
3229/* parse the "ciphers" server keyword */
3230static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3231{
3232 if (!*args[*cur_arg + 1]) {
3233 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
3234 return ERR_ALERT | ERR_FATAL;
3235 }
3236
3237 free(newsrv->ssl_ctx.ciphers);
3238 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
3239 return 0;
3240}
3241
Emeric Brunef42d922012-10-11 16:11:36 +02003242/* parse the "crl-file" server keyword */
3243static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3244{
3245#ifndef X509_V_FLAG_CRL_CHECK
3246 if (err)
3247 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
3248 return ERR_ALERT | ERR_FATAL;
3249#else
3250 if (!*args[*cur_arg + 1]) {
3251 if (err)
3252 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
3253 return ERR_ALERT | ERR_FATAL;
3254 }
3255
3256 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3257 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3258 else
3259 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
3260
3261 return 0;
3262#endif
3263}
3264
Emeric Bruna7aa3092012-10-26 12:58:00 +02003265/* parse the "crt" server keyword */
3266static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3267{
3268 if (!*args[*cur_arg + 1]) {
3269 if (err)
3270 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
3271 return ERR_ALERT | ERR_FATAL;
3272 }
3273
3274 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
3275 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3276 else
3277 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
3278
3279 return 0;
3280}
Emeric Brunef42d922012-10-11 16:11:36 +02003281
Willy Tarreau92faadf2012-10-10 23:04:25 +02003282/* parse the "force-sslv3" server keyword */
3283static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3284{
3285 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
3286 return 0;
3287}
3288
3289/* parse the "force-tlsv10" server keyword */
3290static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3291{
3292 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
3293 return 0;
3294}
3295
3296/* parse the "force-tlsv11" server keyword */
3297static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3298{
3299#if SSL_OP_NO_TLSv1_1
3300 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
3301 return 0;
3302#else
3303 if (err)
3304 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
3305 return ERR_ALERT | ERR_FATAL;
3306#endif
3307}
3308
3309/* parse the "force-tlsv12" server keyword */
3310static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3311{
3312#if SSL_OP_NO_TLSv1_2
3313 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
3314 return 0;
3315#else
3316 if (err)
3317 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
3318 return ERR_ALERT | ERR_FATAL;
3319#endif
3320}
3321
3322/* parse the "no-sslv3" server keyword */
3323static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3324{
3325 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
3326 return 0;
3327}
3328
3329/* parse the "no-tlsv10" server keyword */
3330static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3331{
3332 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
3333 return 0;
3334}
3335
3336/* parse the "no-tlsv11" server keyword */
3337static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3338{
3339 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
3340 return 0;
3341}
3342
3343/* parse the "no-tlsv12" server keyword */
3344static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3345{
3346 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
3347 return 0;
3348}
3349
Emeric Brunf9c5c472012-10-11 15:28:34 +02003350/* parse the "no-tls-tickets" server keyword */
3351static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3352{
3353 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
3354 return 0;
3355}
3356
Willy Tarreau92faadf2012-10-10 23:04:25 +02003357/* parse the "ssl" server keyword */
3358static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3359{
3360 newsrv->use_ssl = 1;
3361 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3362 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3363 return 0;
3364}
3365
Emeric Brunef42d922012-10-11 16:11:36 +02003366/* parse the "verify" server keyword */
3367static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3368{
3369 if (!*args[*cur_arg + 1]) {
3370 if (err)
3371 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
3372 return ERR_ALERT | ERR_FATAL;
3373 }
3374
3375 if (strcmp(args[*cur_arg + 1], "none") == 0)
3376 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
3377 else if (strcmp(args[*cur_arg + 1], "required") == 0)
3378 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
3379 else {
3380 if (err)
3381 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
3382 args[*cur_arg], args[*cur_arg + 1]);
3383 return ERR_ALERT | ERR_FATAL;
3384 }
3385
Evan Broderbe554312013-06-27 00:05:25 -07003386 return 0;
3387}
3388
3389/* parse the "verifyhost" server keyword */
3390static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3391{
3392 if (!*args[*cur_arg + 1]) {
3393 if (err)
3394 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
3395 return ERR_ALERT | ERR_FATAL;
3396 }
3397
3398 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
3399
Emeric Brunef42d922012-10-11 16:11:36 +02003400 return 0;
3401}
3402
Willy Tarreau7875d092012-09-10 08:20:03 +02003403/* Note: must not be declared <const> as its list will be overwritten.
3404 * Please take care of keeping this list alphabetically sorted.
3405 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003406static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Willy Tarreau80aca902013-01-07 15:42:20 +01003407 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3408 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3409 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3410 { "ssl_c_i_dn", smp_fetch_ssl_c_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3411 { "ssl_c_key_alg", smp_fetch_ssl_c_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3412 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3413 { "ssl_c_notbefore", smp_fetch_ssl_c_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3414 { "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3415 { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3416 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
James Votha051b4a2013-05-14 20:37:59 +02003417 { "ssl_c_sha1", smp_fetch_ssl_c_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01003418 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3419 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3420 { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3421 { "ssl_f_i_dn", smp_fetch_ssl_f_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3422 { "ssl_f_key_alg", smp_fetch_ssl_f_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3423 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3424 { "ssl_f_notbefore", smp_fetch_ssl_f_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3425 { "ssl_f_sig_alg", smp_fetch_ssl_f_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3426 { "ssl_f_s_dn", smp_fetch_ssl_f_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3427 { "ssl_f_serial", smp_fetch_ssl_f_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3428 { "ssl_f_version", smp_fetch_ssl_f_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3429 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3430 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3431 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3432 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3433 { "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 +02003434#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau80aca902013-01-07 15:42:20 +01003435 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003436#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003437#ifdef OPENSSL_ALPN_NEGOTIATED
3438 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3439#endif
Willy Tarreau80aca902013-01-07 15:42:20 +01003440 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3441 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3442 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_CBIN, SMP_USE_L5CLI },
3443 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreau7875d092012-09-10 08:20:03 +02003444 { NULL, NULL, 0, 0, 0 },
3445}};
3446
3447/* Note: must not be declared <const> as its list will be overwritten.
3448 * Please take care of keeping this list alphabetically sorted.
3449 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003450static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003451 { "ssl_c_i_dn", NULL, pat_parse_str, pat_match_str },
3452 { "ssl_c_key_alg", NULL, pat_parse_str, pat_match_str },
3453 { "ssl_c_notafter", NULL, pat_parse_str, pat_match_str },
3454 { "ssl_c_notbefore", NULL, pat_parse_str, pat_match_str },
3455 { "ssl_c_sig_alg", NULL, pat_parse_str, pat_match_str },
3456 { "ssl_c_s_dn", NULL, pat_parse_str, pat_match_str },
3457 { "ssl_c_serial", NULL, pat_parse_bin, pat_match_bin },
3458 { "ssl_f_i_dn", NULL, pat_parse_str, pat_match_str },
3459 { "ssl_f_key_alg", NULL, pat_parse_str, pat_match_str },
3460 { "ssl_f_notafter", NULL, pat_parse_str, pat_match_str },
3461 { "ssl_f_notbefore", NULL, pat_parse_str, pat_match_str },
3462 { "ssl_f_sig_alg", NULL, pat_parse_str, pat_match_str },
3463 { "ssl_f_s_dn", NULL, pat_parse_str, pat_match_str },
3464 { "ssl_f_serial", NULL, pat_parse_bin, pat_match_bin },
3465 { "ssl_fc_cipher", NULL, pat_parse_str, pat_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003466#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003467 { "ssl_fc_npn", NULL, pat_parse_str, pat_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003468#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003469#ifdef OPENSSL_ALPN_NEGOTIATED
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003470 { "ssl_fc_alpn", NULL, pat_parse_str, pat_match_str },
Willy Tarreauab861d32013-04-02 02:30:41 +02003471#endif
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003472 { "ssl_fc_protocol", NULL, pat_parse_str, pat_match_str },
3473 { "ssl_fc_sni", "ssl_fc_sni", pat_parse_str, pat_match_str },
3474 { "ssl_fc_sni_end", "ssl_fc_sni", pat_parse_str, pat_match_end },
3475 { "ssl_fc_sni_reg", "ssl_fc_sni", pat_parse_reg, pat_match_reg },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01003476 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02003477}};
3478
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003479/* Note: must not be declared <const> as its list will be overwritten.
3480 * Please take care of keeping this list alphabetically sorted, doing so helps
3481 * all code contributors.
3482 * Optional keywords are also declared with a NULL ->parse() function so that
3483 * the config parser can report an appropriate error when a known keyword was
3484 * not enabled.
3485 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02003486static struct bind_kw_list bind_kws = { "SSL", { }, {
Willy Tarreauab861d32013-04-02 02:30:41 +02003487 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003488 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003489 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
3490 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003491 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003492 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
3493 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003494 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003495 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003496 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
3497 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
3498 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
3499 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02003500 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
3501 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
3502 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
3503 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003504 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003505 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003506 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003507 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003508 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003509 { NULL, NULL, 0 },
3510}};
Emeric Brun46591952012-05-18 15:47:34 +02003511
Willy Tarreau92faadf2012-10-10 23:04:25 +02003512/* Note: must not be declared <const> as its list will be overwritten.
3513 * Please take care of keeping this list alphabetically sorted, doing so helps
3514 * all code contributors.
3515 * Optional keywords are also declared with a NULL ->parse() function so that
3516 * the config parser can report an appropriate error when a known keyword was
3517 * not enabled.
3518 */
3519static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02003520 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003521 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
3522 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02003523 { "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 +02003524 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003525 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
3526 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
3527 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
3528 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
3529 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
3530 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
3531 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
3532 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02003533 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003534 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02003535 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Evan Broderbe554312013-06-27 00:05:25 -07003536 { "verifyhost", srv_parse_verifyhost, 1, 0 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02003537 { NULL, NULL, 0, 0 },
3538}};
3539
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003540/* transport-layer operations for SSL sockets */
3541struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02003542 .snd_buf = ssl_sock_from_buf,
3543 .rcv_buf = ssl_sock_to_buf,
3544 .rcv_pipe = NULL,
3545 .snd_pipe = NULL,
3546 .shutr = NULL,
3547 .shutw = ssl_sock_shutw,
3548 .close = ssl_sock_close,
3549 .init = ssl_sock_init,
3550};
3551
3552__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02003553static void __ssl_sock_init(void)
3554{
Emeric Brun46591952012-05-18 15:47:34 +02003555 STACK_OF(SSL_COMP)* cm;
3556
3557 SSL_library_init();
3558 cm = SSL_COMP_get_compression_methods();
3559 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02003560 sample_register_fetches(&sample_fetch_keywords);
3561 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003562 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02003563 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02003564}
3565
3566/*
3567 * Local variables:
3568 * c-indent-level: 8
3569 * c-basic-offset: 8
3570 * End:
3571 */