blob: d30a8eb88c5472313c9de9937804381cbf128b0b [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);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001194 __conn_sock_want_send(conn);
1195 fd_cant_send(conn->t.sock.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01001196 return 0;
1197 }
1198 else if (ret == SSL_ERROR_WANT_READ) {
1199 /* handshake may have been completed but we have
1200 * no more data to read.
1201 */
1202 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
1203 ret = 1;
1204 goto reneg_ok;
1205 }
1206 /* SSL handshake needs to read, L4 connection is ready */
1207 if (conn->flags & CO_FL_WAIT_L4_CONN)
1208 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1209 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001210 __conn_sock_want_recv(conn);
1211 fd_cant_recv(conn->t.sock.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01001212 return 0;
1213 }
1214 else if (ret == SSL_ERROR_SYSCALL) {
1215 /* if errno is null, then connection was successfully established */
1216 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1217 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001218 if (!conn->err_code) {
1219 if (!((SSL *)conn->xprt_ctx)->packet_length)
1220 if (!errno)
1221 conn->err_code = CO_ER_SSL_EMPTY;
1222 else
1223 conn->err_code = CO_ER_SSL_ABORT;
1224 else
1225 conn->err_code = CO_ER_SSL_HANDSHAKE;
1226 }
Emeric Brun674b7432012-11-08 19:21:55 +01001227 goto out_error;
1228 }
1229 else {
1230 /* Fail on all other handshake errors */
1231 /* Note: OpenSSL may leave unread bytes in the socket's
1232 * buffer, causing an RST to be emitted upon close() on
1233 * TCP sockets. We first try to drain possibly pending
1234 * data to avoid this as much as possible.
1235 */
Willy Tarreau46be2e52014-01-20 12:10:52 +01001236 conn_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01001237 if (!conn->err_code)
1238 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01001239 goto out_error;
1240 }
1241 }
1242 /* read some data: consider handshake completed */
1243 goto reneg_ok;
1244 }
1245
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001246 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001247 if (ret != 1) {
1248 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001249 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001250
1251 if (ret == SSL_ERROR_WANT_WRITE) {
1252 /* SSL handshake needs to write, L4 connection may not be ready */
1253 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001254 __conn_sock_want_send(conn);
1255 fd_cant_send(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001256 return 0;
1257 }
1258 else if (ret == SSL_ERROR_WANT_READ) {
1259 /* SSL handshake needs to read, L4 connection is ready */
1260 if (conn->flags & CO_FL_WAIT_L4_CONN)
1261 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1262 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001263 __conn_sock_want_recv(conn);
1264 fd_cant_recv(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001265 return 0;
1266 }
Willy Tarreau89230192012-09-28 20:22:13 +02001267 else if (ret == SSL_ERROR_SYSCALL) {
1268 /* if errno is null, then connection was successfully established */
1269 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1270 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001271
1272 if (!((SSL *)conn->xprt_ctx)->packet_length)
1273 if (!errno)
1274 conn->err_code = CO_ER_SSL_EMPTY;
1275 else
1276 conn->err_code = CO_ER_SSL_ABORT;
1277 else
1278 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +02001279 goto out_error;
1280 }
Emeric Brun46591952012-05-18 15:47:34 +02001281 else {
1282 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02001283 /* Note: OpenSSL may leave unread bytes in the socket's
1284 * buffer, causing an RST to be emitted upon close() on
1285 * TCP sockets. We first try to drain possibly pending
1286 * data to avoid this as much as possible.
1287 */
Willy Tarreau46be2e52014-01-20 12:10:52 +01001288 conn_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01001289 if (!conn->err_code)
1290 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001291 goto out_error;
1292 }
1293 }
1294
Emeric Brun674b7432012-11-08 19:21:55 +01001295reneg_ok:
1296
Emeric Brun46591952012-05-18 15:47:34 +02001297 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001298 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001299 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +02001300 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001301 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1302 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001303
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001304 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001305 }
1306 }
1307
1308 /* The connection is now established at both layers, it's time to leave */
1309 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1310 return 1;
1311
1312 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001313 /* Clear openssl global errors stack */
1314 ERR_clear_error();
1315
Emeric Brun9fa89732012-10-04 17:09:56 +02001316 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001317 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1318 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1319 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001320 }
1321
Emeric Brun46591952012-05-18 15:47:34 +02001322 /* Fail on all other handshake errors */
1323 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001324 if (!conn->err_code)
1325 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001326 return 0;
1327}
1328
1329/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01001330 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02001331 * buffer wraps, in which case a second call may be performed. The connection's
1332 * flags are updated with whatever special event is detected (error, read0,
1333 * empty). The caller is responsible for taking care of those events and
1334 * avoiding the call if inappropriate. The function does not call the
1335 * connection's polling update function, so the caller is responsible for this.
1336 */
1337static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1338{
1339 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01001340 int try;
Emeric Brun46591952012-05-18 15:47:34 +02001341
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001342 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001343 goto out_error;
1344
1345 if (conn->flags & CO_FL_HANDSHAKE)
1346 /* a handshake was requested */
1347 return 0;
1348
Willy Tarreauabf08d92014-01-14 11:31:27 +01001349 /* let's realign the buffer to optimize I/O */
1350 if (buffer_empty(buf))
Emeric Brun46591952012-05-18 15:47:34 +02001351 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02001352
1353 /* read the largest possible block. For this, we perform only one call
1354 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1355 * in which case we accept to do it once again. A new attempt is made on
1356 * EINTR too.
1357 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01001358 while (count > 0) {
Willy Tarreauabf08d92014-01-14 11:31:27 +01001359 /* first check if we have some room after p+i */
1360 try = buf->data + buf->size - (buf->p + buf->i);
1361 /* otherwise continue between data and p-o */
1362 if (try <= 0) {
1363 try = buf->p - (buf->data + buf->o);
1364 if (try <= 0)
1365 break;
1366 }
1367 if (try > count)
1368 try = count;
1369
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001370 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001371 if (conn->flags & CO_FL_ERROR) {
1372 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001373 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001374 }
Emeric Brun46591952012-05-18 15:47:34 +02001375 if (ret > 0) {
1376 buf->i += ret;
1377 done += ret;
1378 if (ret < try)
1379 break;
1380 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02001381 }
1382 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001383 ret = SSL_get_error(conn->xprt_ctx, ret);
1384 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001385 /* error on protocol or underlying transport */
1386 if ((ret != SSL_ERROR_SYSCALL)
1387 || (errno && (errno != EAGAIN)))
1388 conn->flags |= CO_FL_ERROR;
1389
Emeric Brun644cde02012-12-14 11:21:13 +01001390 /* Clear openssl global errors stack */
1391 ERR_clear_error();
1392 }
Emeric Brun46591952012-05-18 15:47:34 +02001393 goto read0;
1394 }
1395 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001396 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001397 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001398 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001399 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001400 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001401 break;
1402 }
1403 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001404 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1405 /* handshake is running, and it may need to re-enable read */
1406 conn->flags |= CO_FL_SSL_WAIT_HS;
1407 __conn_sock_want_recv(conn);
1408 break;
1409 }
Emeric Brun46591952012-05-18 15:47:34 +02001410 /* we need to poll for retry a read later */
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001411 fd_cant_recv(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001412 break;
1413 }
1414 /* otherwise it's a real error */
1415 goto out_error;
1416 }
1417 }
1418 return done;
1419
1420 read0:
1421 conn_sock_read0(conn);
1422 return done;
1423 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001424 /* Clear openssl global errors stack */
1425 ERR_clear_error();
1426
Emeric Brun46591952012-05-18 15:47:34 +02001427 conn->flags |= CO_FL_ERROR;
1428 return done;
1429}
1430
1431
1432/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1433 * <flags> may contain MSG_MORE to make the system hold on without sending
1434 * data too fast, but this flag is ignored at the moment.
1435 * Only one call to send() is performed, unless the buffer wraps, in which case
1436 * a second call may be performed. The connection's flags are updated with
1437 * whatever special event is detected (error, empty). The caller is responsible
1438 * for taking care of those events and avoiding the call if inappropriate. The
1439 * function does not call the connection's polling update function, so the caller
1440 * is responsible for this.
1441 */
1442static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1443{
1444 int ret, try, done;
1445
1446 done = 0;
1447
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001448 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001449 goto out_error;
1450
1451 if (conn->flags & CO_FL_HANDSHAKE)
1452 /* a handshake was requested */
1453 return 0;
1454
1455 /* send the largest possible block. For this we perform only one call
1456 * to send() unless the buffer wraps and we exactly fill the first hunk,
1457 * in which case we accept to do it once again.
1458 */
1459 while (buf->o) {
Kevin Hestercad82342013-05-30 15:12:41 -07001460 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01001461
1462 if (global.tune.ssl_max_record && try > global.tune.ssl_max_record)
1463 try = global.tune.ssl_max_record;
1464
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001465 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001466 if (conn->flags & CO_FL_ERROR) {
1467 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001468 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001469 }
Emeric Brun46591952012-05-18 15:47:34 +02001470 if (ret > 0) {
1471 buf->o -= ret;
1472 done += ret;
1473
Willy Tarreau5fb38032012-12-16 19:39:09 +01001474 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001475 /* optimize data alignment in the buffer */
1476 buf->p = buf->data;
1477
1478 /* if the system buffer is full, don't insist */
1479 if (ret < try)
1480 break;
1481 }
1482 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001483 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001484 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001485 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1486 /* handshake is running, and it may need to re-enable write */
1487 conn->flags |= CO_FL_SSL_WAIT_HS;
1488 __conn_sock_want_send(conn);
1489 break;
1490 }
Emeric Brun46591952012-05-18 15:47:34 +02001491 /* we need to poll to retry a write later */
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001492 fd_cant_send(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001493 break;
1494 }
1495 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001496 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001497 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001498 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001499 break;
1500 }
1501 goto out_error;
1502 }
1503 }
1504 return done;
1505
1506 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001507 /* Clear openssl global errors stack */
1508 ERR_clear_error();
1509
Emeric Brun46591952012-05-18 15:47:34 +02001510 conn->flags |= CO_FL_ERROR;
1511 return done;
1512}
1513
Emeric Brun46591952012-05-18 15:47:34 +02001514static void ssl_sock_close(struct connection *conn) {
1515
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001516 if (conn->xprt_ctx) {
1517 SSL_free(conn->xprt_ctx);
1518 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001519 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001520 }
Emeric Brun46591952012-05-18 15:47:34 +02001521}
1522
1523/* This function tries to perform a clean shutdown on an SSL connection, and in
1524 * any case, flags the connection as reusable if no handshake was in progress.
1525 */
1526static void ssl_sock_shutw(struct connection *conn, int clean)
1527{
1528 if (conn->flags & CO_FL_HANDSHAKE)
1529 return;
1530 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001531 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1532 /* Clear openssl global errors stack */
1533 ERR_clear_error();
1534 }
Emeric Brun46591952012-05-18 15:47:34 +02001535
1536 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001537 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001538}
1539
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001540/* used for logging, may be changed for a sample fetch later */
1541const char *ssl_sock_get_cipher_name(struct connection *conn)
1542{
1543 if (!conn->xprt && !conn->xprt_ctx)
1544 return NULL;
1545 return SSL_get_cipher_name(conn->xprt_ctx);
1546}
1547
1548/* used for logging, may be changed for a sample fetch later */
1549const char *ssl_sock_get_proto_version(struct connection *conn)
1550{
1551 if (!conn->xprt && !conn->xprt_ctx)
1552 return NULL;
1553 return SSL_get_version(conn->xprt_ctx);
1554}
1555
Willy Tarreau8d598402012-10-22 17:58:39 +02001556/* Extract a serial from a cert, and copy it to a chunk.
1557 * Returns 1 if serial is found and copied, 0 if no serial found and
1558 * -1 if output is not large enough.
1559 */
1560static int
1561ssl_sock_get_serial(X509 *crt, struct chunk *out)
1562{
1563 ASN1_INTEGER *serial;
1564
1565 serial = X509_get_serialNumber(crt);
1566 if (!serial)
1567 return 0;
1568
1569 if (out->size < serial->length)
1570 return -1;
1571
1572 memcpy(out->str, serial->data, serial->length);
1573 out->len = serial->length;
1574 return 1;
1575}
1576
Emeric Brunce5ad802012-10-22 14:11:22 +02001577
1578/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1579 * Returns 1 if serial is found and copied, 0 if no valid time found
1580 * and -1 if output is not large enough.
1581 */
1582static int
1583ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1584{
1585 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1586 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1587
1588 if (gentm->length < 12)
1589 return 0;
1590 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1591 return 0;
1592 if (out->size < gentm->length-2)
1593 return -1;
1594
1595 memcpy(out->str, gentm->data+2, gentm->length-2);
1596 out->len = gentm->length-2;
1597 return 1;
1598 }
1599 else if (tm->type == V_ASN1_UTCTIME) {
1600 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1601
1602 if (utctm->length < 10)
1603 return 0;
1604 if (utctm->data[0] >= 0x35)
1605 return 0;
1606 if (out->size < utctm->length)
1607 return -1;
1608
1609 memcpy(out->str, utctm->data, utctm->length);
1610 out->len = utctm->length;
1611 return 1;
1612 }
1613
1614 return 0;
1615}
1616
Emeric Brun87855892012-10-17 17:39:35 +02001617/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1618 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1619 */
1620static int
1621ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1622{
1623 X509_NAME_ENTRY *ne;
1624 int i, j, n;
1625 int cur = 0;
1626 const char *s;
1627 char tmp[128];
1628
1629 out->len = 0;
1630 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1631 if (pos < 0)
1632 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1633 else
1634 j = i;
1635
1636 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1637 n = OBJ_obj2nid(ne->object);
1638 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1639 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1640 s = tmp;
1641 }
1642
1643 if (chunk_strcasecmp(entry, s) != 0)
1644 continue;
1645
1646 if (pos < 0)
1647 cur--;
1648 else
1649 cur++;
1650
1651 if (cur != pos)
1652 continue;
1653
1654 if (ne->value->length > out->size)
1655 return -1;
1656
1657 memcpy(out->str, ne->value->data, ne->value->length);
1658 out->len = ne->value->length;
1659 return 1;
1660 }
1661
1662 return 0;
1663
1664}
1665
1666/* Extract and format full DN from a X509_NAME and copy result into a chunk
1667 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1668 */
1669static int
1670ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1671{
1672 X509_NAME_ENTRY *ne;
1673 int i, n, ln;
1674 int l = 0;
1675 const char *s;
1676 char *p;
1677 char tmp[128];
1678
1679 out->len = 0;
1680 p = out->str;
1681 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1682 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1683 n = OBJ_obj2nid(ne->object);
1684 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1685 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1686 s = tmp;
1687 }
1688 ln = strlen(s);
1689
1690 l += 1 + ln + 1 + ne->value->length;
1691 if (l > out->size)
1692 return -1;
1693 out->len = l;
1694
1695 *(p++)='/';
1696 memcpy(p, s, ln);
1697 p += ln;
1698 *(p++)='=';
1699 memcpy(p, ne->value->data, ne->value->length);
1700 p += ne->value->length;
1701 }
1702
1703 if (!out->len)
1704 return 0;
1705
1706 return 1;
1707}
1708
Willy Tarreau7875d092012-09-10 08:20:03 +02001709/***** Below are some sample fetching functions for ACL/patterns *****/
1710
Emeric Brune64aef12012-09-21 13:15:06 +02001711/* boolean, returns true if client cert was present */
1712static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001713smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001714 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brune64aef12012-09-21 13:15:06 +02001715{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001716 struct connection *conn;
1717
1718 if (!l4)
1719 return 0;
1720
1721 conn = objt_conn(l4->si[0].end);
1722 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001723 return 0;
1724
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001725 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001726 smp->flags |= SMP_F_MAY_CHANGE;
1727 return 0;
1728 }
1729
1730 smp->flags = 0;
1731 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001732 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001733
1734 return 1;
1735}
1736
Willy Tarreau8d598402012-10-22 17:58:39 +02001737/* bin, returns serial in a binary chunk */
1738static int
1739smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001740 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02001741{
1742 X509 *crt = NULL;
1743 int ret = 0;
1744 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001745 struct connection *conn;
1746
1747 if (!l4)
1748 return 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02001749
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001750 conn = objt_conn(l4->si[0].end);
1751 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001752 return 0;
1753
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001754 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001755 smp->flags |= SMP_F_MAY_CHANGE;
1756 return 0;
1757 }
1758
1759 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001760 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001761 if (!crt)
1762 goto out;
1763
Willy Tarreau47ca5452012-12-23 20:22:19 +01001764 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001765 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1766 goto out;
1767
1768 smp->data.str = *smp_trash;
1769 smp->type = SMP_T_BIN;
1770 ret = 1;
1771out:
1772 if (crt)
1773 X509_free(crt);
1774 return ret;
1775}
Emeric Brune64aef12012-09-21 13:15:06 +02001776
James Votha051b4a2013-05-14 20:37:59 +02001777/* bin, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk */
1778static int
1779smp_fetch_ssl_c_sha1(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001780 const struct arg *args, struct sample *smp, const char *kw)
James Votha051b4a2013-05-14 20:37:59 +02001781{
1782 X509 *crt = NULL;
1783 const EVP_MD *digest;
1784 int ret = 0;
1785 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001786 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02001787
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001788 if (!l4)
James Votha051b4a2013-05-14 20:37:59 +02001789 return 0;
1790
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001791 conn = objt_conn(l4->si[0].end);
1792 if (!conn || conn->xprt != &ssl_sock)
1793 return 0;
1794
1795 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02001796 smp->flags |= SMP_F_MAY_CHANGE;
1797 return 0;
1798 }
1799
1800 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001801 crt = SSL_get_peer_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02001802 if (!crt)
1803 goto out;
1804
1805 smp_trash = get_trash_chunk();
1806 digest = EVP_sha1();
1807 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
1808
1809 smp->data.str = *smp_trash;
1810 smp->type = SMP_T_BIN;
1811 ret = 1;
1812out:
1813 if (crt)
1814 X509_free(crt);
1815 return ret;
1816}
1817
Emeric Brunce5ad802012-10-22 14:11:22 +02001818/*str, returns notafter date in ASN1_UTCTIME format */
1819static int
1820smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001821 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001822{
1823 X509 *crt = NULL;
1824 int ret = 0;
1825 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001826 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02001827
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001828 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02001829 return 0;
1830
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001831 conn = objt_conn(l4->si[0].end);
1832 if (!conn || conn->xprt != &ssl_sock)
1833 return 0;
1834
1835 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001836 smp->flags |= SMP_F_MAY_CHANGE;
1837 return 0;
1838 }
1839
1840 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001841 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001842 if (!crt)
1843 goto out;
1844
Willy Tarreau47ca5452012-12-23 20:22:19 +01001845 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001846 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1847 goto out;
1848
1849 smp->data.str = *smp_trash;
1850 smp->type = SMP_T_STR;
1851 ret = 1;
1852out:
1853 if (crt)
1854 X509_free(crt);
1855 return ret;
1856}
1857
Emeric Brun87855892012-10-17 17:39:35 +02001858/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1859static int
1860smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001861 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02001862{
1863 X509 *crt = NULL;
1864 X509_NAME *name;
1865 int ret = 0;
1866 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001867 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02001868
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001869 if (!l4)
Emeric Brun87855892012-10-17 17:39:35 +02001870 return 0;
1871
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001872 conn = objt_conn(l4->si[0].end);
1873 if (!conn || conn->xprt != &ssl_sock)
1874 return 0;
1875
1876 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001877 smp->flags |= SMP_F_MAY_CHANGE;
1878 return 0;
1879 }
1880
1881 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001882 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001883 if (!crt)
1884 goto out;
1885
1886 name = X509_get_issuer_name(crt);
1887 if (!name)
1888 goto out;
1889
Willy Tarreau47ca5452012-12-23 20:22:19 +01001890 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001891 if (args && args[0].type == ARGT_STR) {
1892 int pos = 1;
1893
1894 if (args[1].type == ARGT_SINT)
1895 pos = args[1].data.sint;
1896 else if (args[1].type == ARGT_UINT)
1897 pos =(int)args[1].data.uint;
1898
1899 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1900 goto out;
1901 }
1902 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1903 goto out;
1904
1905 smp->type = SMP_T_STR;
1906 smp->data.str = *smp_trash;
1907 ret = 1;
1908out:
1909 if (crt)
1910 X509_free(crt);
1911 return ret;
1912}
1913
Emeric Brunce5ad802012-10-22 14:11:22 +02001914/*str, returns notbefore date in ASN1_UTCTIME format */
1915static int
1916smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001917 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001918{
1919 X509 *crt = NULL;
1920 int ret = 0;
1921 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001922 struct connection *conn;
1923
1924 if (!l4)
1925 return 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02001926
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001927 conn = objt_conn(l4->si[0].end);
1928 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001929 return 0;
1930
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001931 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001932 smp->flags |= SMP_F_MAY_CHANGE;
1933 return 0;
1934 }
1935
1936 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001937 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001938 if (!crt)
1939 goto out;
1940
Willy Tarreau47ca5452012-12-23 20:22:19 +01001941 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001942 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1943 goto out;
1944
1945 smp->data.str = *smp_trash;
1946 smp->type = SMP_T_STR;
1947 ret = 1;
1948out:
1949 if (crt)
1950 X509_free(crt);
1951 return ret;
1952}
1953
Emeric Brun87855892012-10-17 17:39:35 +02001954/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1955static int
1956smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001957 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02001958{
1959 X509 *crt = NULL;
1960 X509_NAME *name;
1961 int ret = 0;
1962 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001963 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02001964
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001965 if (!l4)
Emeric Brun87855892012-10-17 17:39:35 +02001966 return 0;
1967
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001968 conn = objt_conn(l4->si[0].end);
1969 if (!conn || conn->xprt != &ssl_sock)
1970 return 0;
1971
1972 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001973 smp->flags |= SMP_F_MAY_CHANGE;
1974 return 0;
1975 }
1976
1977 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001978 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001979 if (!crt)
1980 goto out;
1981
1982 name = X509_get_subject_name(crt);
1983 if (!name)
1984 goto out;
1985
Willy Tarreau47ca5452012-12-23 20:22:19 +01001986 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001987 if (args && args[0].type == ARGT_STR) {
1988 int pos = 1;
1989
1990 if (args[1].type == ARGT_SINT)
1991 pos = args[1].data.sint;
1992 else if (args[1].type == ARGT_UINT)
1993 pos =(int)args[1].data.uint;
1994
1995 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1996 goto out;
1997 }
1998 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1999 goto out;
2000
2001 smp->type = SMP_T_STR;
2002 smp->data.str = *smp_trash;
2003 ret = 1;
2004out:
2005 if (crt)
2006 X509_free(crt);
2007 return ret;
2008}
Emeric Brun9143d372012-12-20 15:44:16 +01002009
2010/* integer, returns true if current session use a client certificate */
2011static int
2012smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002013 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun9143d372012-12-20 15:44:16 +01002014{
2015 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002016 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01002017
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002018 if (!l4)
Emeric Brun9143d372012-12-20 15:44:16 +01002019 return 0;
2020
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002021 conn = objt_conn(l4->si[0].end);
2022 if (!conn || conn->xprt != &ssl_sock)
2023 return 0;
2024
2025 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01002026 smp->flags |= SMP_F_MAY_CHANGE;
2027 return 0;
2028 }
2029
2030 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002031 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01002032 if (crt) {
2033 X509_free(crt);
2034 }
2035
2036 smp->type = SMP_T_BOOL;
2037 smp->data.uint = (crt != NULL);
2038 return 1;
2039}
2040
Emeric Bruna7359fd2012-10-17 15:03:11 +02002041/* integer, returns the client certificate version */
2042static int
2043smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002044 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002045{
2046 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002047 struct connection *conn;
2048
2049 if (!l4)
2050 return 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02002051
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002052 conn = objt_conn(l4->si[0].end);
2053 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002054 return 0;
2055
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002056 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002057 smp->flags |= SMP_F_MAY_CHANGE;
2058 return 0;
2059 }
2060
2061 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002062 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002063 if (!crt)
2064 return 0;
2065
2066 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2067 X509_free(crt);
2068 smp->type = SMP_T_UINT;
2069
2070 return 1;
2071}
2072
Emeric Brun7f56e742012-10-19 18:15:40 +02002073/* str, returns the client certificate sig alg */
2074static int
2075smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002076 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002077{
2078 X509 *crt;
2079 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002080 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02002081
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002082 if (!l4)
Emeric Brun7f56e742012-10-19 18:15:40 +02002083 return 0;
2084
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002085 conn = objt_conn(l4->si[0].end);
2086 if (!conn || conn->xprt != &ssl_sock)
2087 return 0;
2088
2089 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002090 smp->flags |= SMP_F_MAY_CHANGE;
2091 return 0;
2092 }
2093
2094 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002095 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002096 if (!crt)
2097 return 0;
2098
2099 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2100
2101 smp->data.str.str = (char *)OBJ_nid2sn(nid);
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002102 if (!smp->data.str.str) {
2103 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02002104 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002105 }
Emeric Brun7f56e742012-10-19 18:15:40 +02002106
2107 smp->type = SMP_T_CSTR;
2108 smp->data.str.len = strlen(smp->data.str.str);
2109 X509_free(crt);
2110
2111 return 1;
2112}
2113
Emeric Brun521a0112012-10-22 12:22:55 +02002114/* str, returns the client certificate key alg */
2115static int
2116smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002117 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002118{
2119 X509 *crt;
2120 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002121 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02002122
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002123 if (!l4)
Emeric Brun521a0112012-10-22 12:22:55 +02002124 return 0;
2125
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002126 conn = objt_conn(l4->si[0].end);
2127 if (!conn || conn->xprt != &ssl_sock)
2128 return 0;
2129
2130 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002131 smp->flags |= SMP_F_MAY_CHANGE;
2132 return 0;
2133 }
2134
2135 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002136 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002137 if (!crt)
2138 return 0;
2139
2140 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2141
2142 smp->data.str.str = (char *)OBJ_nid2sn(nid);
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002143 if (!smp->data.str.str) {
2144 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02002145 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002146 }
Emeric Brun521a0112012-10-22 12:22:55 +02002147
2148 smp->type = SMP_T_CSTR;
2149 smp->data.str.len = strlen(smp->data.str.str);
2150 X509_free(crt);
2151
2152 return 1;
2153}
2154
Emeric Brun2525b6b2012-10-18 15:59:43 +02002155/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02002156static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002157smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002158 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002159{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002160 struct connection *conn = objt_conn(l4->si[0].end);
2161
Willy Tarreau7875d092012-09-10 08:20:03 +02002162 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002163 smp->data.uint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02002164 return 1;
2165}
2166
Emeric Brun2525b6b2012-10-18 15:59:43 +02002167/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02002168static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002169smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002170 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002171{
2172#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002173 struct connection *conn = objt_conn(l4->si[0].end);
2174
Willy Tarreau7875d092012-09-10 08:20:03 +02002175 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002176 smp->data.uint = (conn && conn->xprt == &ssl_sock) &&
2177 conn->xprt_ctx &&
2178 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02002179 return 1;
2180#else
2181 return 0;
2182#endif
2183}
2184
Willy Tarreau8d598402012-10-22 17:58:39 +02002185/* bin, returns serial in a binary chunk */
2186static int
2187smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002188 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02002189{
2190 X509 *crt = NULL;
2191 int ret = 0;
2192 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002193 struct connection *conn;
2194
2195 if (!l4)
2196 return 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02002197
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002198 conn = objt_conn(l4->si[0].end);
2199 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02002200 return 0;
2201
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002202 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02002203 smp->flags |= SMP_F_MAY_CHANGE;
2204 return 0;
2205 }
2206
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002207 crt = SSL_get_certificate(conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02002208 if (!crt)
2209 goto out;
2210
Willy Tarreau47ca5452012-12-23 20:22:19 +01002211 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02002212 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
2213 goto out;
2214
2215 smp->data.str = *smp_trash;
2216 smp->type = SMP_T_BIN;
2217 ret = 1;
2218out:
2219 return ret;
2220}
Emeric Brunce5ad802012-10-22 14:11:22 +02002221/*str, returns notafter date in ASN1_UTCTIME format */
2222static int
2223smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002224 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002225{
2226 X509 *crt = NULL;
2227 int ret = 0;
2228 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002229 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02002230
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002231 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02002232 return 0;
2233
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002234 conn = objt_conn(l4->si[0].end);
2235 if (!conn || conn->xprt != &ssl_sock)
2236 return 0;
2237
2238 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002239 smp->flags |= SMP_F_MAY_CHANGE;
2240 return 0;
2241 }
2242
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002243 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002244 if (!crt)
2245 goto out;
2246
Willy Tarreau47ca5452012-12-23 20:22:19 +01002247 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002248 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
2249 goto out;
2250
2251 smp->data.str = *smp_trash;
2252 smp->type = SMP_T_STR;
2253 ret = 1;
2254out:
2255 return ret;
2256}
2257
2258/*str, returns notbefore date in ASN1_UTCTIME format */
2259static int
2260smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002261 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002262{
2263 X509 *crt = NULL;
2264 int ret = 0;
2265 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002266 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02002267
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002268 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02002269 return 0;
2270
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002271 conn = objt_conn(l4->si[0].end);
2272 if (!conn || conn->xprt != &ssl_sock)
2273 return 0;
2274
2275 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002276 smp->flags |= SMP_F_MAY_CHANGE;
2277 return 0;
2278 }
2279
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002280 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002281 if (!crt)
2282 goto out;
2283
Willy Tarreau47ca5452012-12-23 20:22:19 +01002284 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002285 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
2286 goto out;
2287
2288 smp->data.str = *smp_trash;
2289 smp->type = SMP_T_STR;
2290 ret = 1;
2291out:
2292 return ret;
2293}
Willy Tarreau8d598402012-10-22 17:58:39 +02002294
Emeric Bruna7359fd2012-10-17 15:03:11 +02002295/* integer, returns the frontend certificate version */
2296static int
2297smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002298 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002299{
2300 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002301 struct connection *conn;
Emeric Bruna7359fd2012-10-17 15:03:11 +02002302
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002303 if (!l4)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002304 return 0;
2305
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002306 conn = objt_conn(l4->si[0].end);
2307 if (!conn || conn->xprt != &ssl_sock)
2308 return 0;
2309
2310 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002311 smp->flags |= SMP_F_MAY_CHANGE;
2312 return 0;
2313 }
2314
2315 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002316 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002317 if (!crt)
2318 return 0;
2319
2320 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2321 smp->type = SMP_T_UINT;
2322
2323 return 1;
2324}
2325
Emeric Brun7f56e742012-10-19 18:15:40 +02002326/* str, returns the client certificate sig alg */
2327static int
2328smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002329 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002330{
2331 X509 *crt;
2332 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002333 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02002334
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002335 if (!l4)
Emeric Brun7f56e742012-10-19 18:15:40 +02002336 return 0;
2337
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002338 conn = objt_conn(l4->si[0].end);
2339 if (!conn || conn->xprt != &ssl_sock)
2340 return 0;
2341
2342 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002343 smp->flags |= SMP_F_MAY_CHANGE;
2344 return 0;
2345 }
2346
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002347 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002348 if (!crt)
2349 return 0;
2350
2351 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2352
2353 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2354 if (!smp->data.str.str)
2355 return 0;
2356
2357 smp->type = SMP_T_CSTR;
2358 smp->data.str.len = strlen(smp->data.str.str);
2359
2360 return 1;
2361}
2362
Emeric Brun521a0112012-10-22 12:22:55 +02002363/* str, returns the client certificate key alg */
2364static int
2365smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002366 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002367{
2368 X509 *crt;
2369 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002370 struct connection *conn;
2371
2372 if (!l4)
2373 return 0;
Emeric Brun521a0112012-10-22 12:22:55 +02002374
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002375 conn = objt_conn(l4->si[0].end);
2376 if (!conn || conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002377 return 0;
2378
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002379 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002380 smp->flags |= SMP_F_MAY_CHANGE;
2381 return 0;
2382 }
2383
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002384 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002385 if (!crt)
2386 return 0;
2387
2388 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2389
2390 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2391 if (!smp->data.str.str)
2392 return 0;
2393
2394 smp->type = SMP_T_CSTR;
2395 smp->data.str.len = strlen(smp->data.str.str);
2396
2397 return 1;
2398}
2399
Emeric Brun87855892012-10-17 17:39:35 +02002400/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2401static int
2402smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002403 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002404{
2405 X509 *crt = NULL;
2406 X509_NAME *name;
2407 int ret = 0;
2408 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002409 struct connection *conn;
2410
2411 if (!l4)
2412 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02002413
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002414 conn = objt_conn(l4->si[0].end);
2415 if (!conn || conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002416 return 0;
2417
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002418 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002419 smp->flags |= SMP_F_MAY_CHANGE;
2420 return 0;
2421 }
2422
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002423 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002424 if (!crt)
2425 goto out;
2426
2427 name = X509_get_issuer_name(crt);
2428 if (!name)
2429 goto out;
2430
Willy Tarreau47ca5452012-12-23 20:22:19 +01002431 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002432 if (args && args[0].type == ARGT_STR) {
2433 int pos = 1;
2434
2435 if (args[1].type == ARGT_SINT)
2436 pos = args[1].data.sint;
2437 else if (args[1].type == ARGT_UINT)
2438 pos =(int)args[1].data.uint;
2439
2440 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2441 goto out;
2442 }
2443 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2444 goto out;
2445
2446 smp->type = SMP_T_STR;
2447 smp->data.str = *smp_trash;
2448 ret = 1;
2449out:
2450 return ret;
2451}
2452
2453/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2454static int
2455smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002456 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002457{
2458 X509 *crt = NULL;
2459 X509_NAME *name;
2460 int ret = 0;
2461 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002462 struct connection *conn;
2463
2464 if (!l4)
2465 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02002466
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002467 conn = objt_conn(l4->si[0].end);
2468 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002469 return 0;
2470
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002471 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002472 smp->flags |= SMP_F_MAY_CHANGE;
2473 return 0;
2474 }
2475
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002476 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002477 if (!crt)
2478 goto out;
2479
2480 name = X509_get_subject_name(crt);
2481 if (!name)
2482 goto out;
2483
Willy Tarreau47ca5452012-12-23 20:22:19 +01002484 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002485 if (args && args[0].type == ARGT_STR) {
2486 int pos = 1;
2487
2488 if (args[1].type == ARGT_SINT)
2489 pos = args[1].data.sint;
2490 else if (args[1].type == ARGT_UINT)
2491 pos =(int)args[1].data.uint;
2492
2493 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2494 goto out;
2495 }
2496 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2497 goto out;
2498
2499 smp->type = SMP_T_STR;
2500 smp->data.str = *smp_trash;
2501 ret = 1;
2502out:
2503 return ret;
2504}
2505
Emeric Brun589fcad2012-10-16 14:13:26 +02002506static int
2507smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002508 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002509{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002510 struct connection *conn;
2511
Emeric Brun589fcad2012-10-16 14:13:26 +02002512 smp->flags = 0;
2513
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002514 if (!l4)
2515 return 0;
2516
2517 conn = objt_conn(l4->si[0].end);
2518 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002519 return 0;
2520
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002521 smp->data.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002522 if (!smp->data.str.str)
2523 return 0;
2524
2525 smp->type = SMP_T_CSTR;
2526 smp->data.str.len = strlen(smp->data.str.str);
2527
2528 return 1;
2529}
2530
2531static int
2532smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002533 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002534{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002535 struct connection *conn;
2536
Emeric Brun589fcad2012-10-16 14:13:26 +02002537 smp->flags = 0;
2538
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002539 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002540 return 0;
2541
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002542 conn = objt_conn(l4->si[0].end);
2543 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002544 return 0;
2545
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002546 if (!SSL_get_cipher_bits(conn->xprt_ctx, (int *)&smp->data.uint))
2547 return 0;
2548
Emeric Brun589fcad2012-10-16 14:13:26 +02002549 smp->type = SMP_T_UINT;
2550
2551 return 1;
2552}
2553
2554static int
2555smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002556 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002557{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002558 struct connection *conn;
2559
Emeric Brun589fcad2012-10-16 14:13:26 +02002560 smp->flags = 0;
2561
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002562 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002563 return 0;
2564
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002565 conn = objt_conn(l4->si[0].end);
2566 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2567 return 0;
2568
2569 smp->data.uint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002570 if (!smp->data.uint)
2571 return 0;
2572
2573 smp->type = SMP_T_UINT;
2574
2575 return 1;
2576}
2577
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002578#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002579static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002580smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002581 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002582{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002583 struct connection *conn;
2584
Willy Tarreaua33c6542012-10-15 13:19:06 +02002585 smp->flags = 0;
2586 smp->type = SMP_T_CSTR;
2587
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002588 if (!l4)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002589 return 0;
2590
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002591 conn = objt_conn(l4->si[0].end);
2592 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2593 return 0;
2594
Willy Tarreaua33c6542012-10-15 13:19:06 +02002595 smp->data.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002596 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002597 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2598
2599 if (!smp->data.str.str)
2600 return 0;
2601
2602 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002603}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002604#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002605
Willy Tarreauab861d32013-04-02 02:30:41 +02002606#ifdef OPENSSL_ALPN_NEGOTIATED
2607static int
2608smp_fetch_ssl_fc_alpn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002609 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreauab861d32013-04-02 02:30:41 +02002610{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002611 struct connection *conn;
2612
Willy Tarreauab861d32013-04-02 02:30:41 +02002613 smp->flags = 0;
2614 smp->type = SMP_T_CSTR;
2615
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002616 if (!l4)
2617 return 0;
2618
2619 conn = objt_conn(l4->si[0].end);
2620 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02002621 return 0;
2622
2623 smp->data.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002624 SSL_get0_alpn_negotiated(conn->xprt_ctx,
Willy Tarreauab861d32013-04-02 02:30:41 +02002625 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2626
2627 if (!smp->data.str.str)
2628 return 0;
2629
2630 return 1;
2631}
2632#endif
2633
Willy Tarreaua33c6542012-10-15 13:19:06 +02002634static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002635smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002636 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002637{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002638 struct connection *conn;
2639
Emeric Brun589fcad2012-10-16 14:13:26 +02002640 smp->flags = 0;
2641
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002642 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002643 return 0;
2644
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002645 conn = objt_conn(l4->si[0].end);
2646 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2647 return 0;
2648
2649 smp->data.str.str = (char *)SSL_get_version(conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002650 if (!smp->data.str.str)
2651 return 0;
2652
2653 smp->type = SMP_T_CSTR;
2654 smp->data.str.len = strlen(smp->data.str.str);
2655
2656 return 1;
2657}
2658
2659static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002660smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002661 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunfe68f682012-10-16 14:59:28 +02002662{
2663#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2664 SSL_SESSION *sess;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002665 struct connection *conn;
Emeric Brunfe68f682012-10-16 14:59:28 +02002666
2667 smp->flags = 0;
2668 smp->type = SMP_T_CBIN;
2669
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002670 if (!l4)
Emeric Brunfe68f682012-10-16 14:59:28 +02002671 return 0;
2672
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002673 conn = objt_conn(l4->si[0].end);
2674 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2675 return 0;
2676
2677 sess = SSL_get_session(conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002678 if (!sess)
2679 return 0;
2680
2681 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2682 if (!smp->data.str.str || !&smp->data.str.len)
2683 return 0;
2684
2685 return 1;
2686#else
2687 return 0;
2688#endif
2689}
2690
2691static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002692smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002693 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002694{
2695#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002696 struct connection *conn;
2697
Willy Tarreau7875d092012-09-10 08:20:03 +02002698 smp->flags = 0;
2699 smp->type = SMP_T_CSTR;
2700
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002701 if (!l4)
Willy Tarreau7875d092012-09-10 08:20:03 +02002702 return 0;
2703
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002704 conn = objt_conn(l4->si[0].end);
2705 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2706 return 0;
2707
2708 smp->data.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau3e394c92012-09-14 23:56:58 +02002709 if (!smp->data.str.str)
2710 return 0;
2711
Willy Tarreau7875d092012-09-10 08:20:03 +02002712 smp->data.str.len = strlen(smp->data.str.str);
2713 return 1;
2714#else
2715 return 0;
2716#endif
2717}
2718
Emeric Brun2525b6b2012-10-18 15:59:43 +02002719/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002720static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002721smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002722 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002723{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002724 struct connection *conn;
2725
2726 if (!l4)
Emeric Brunf282a812012-09-21 15:27:54 +02002727 return 0;
2728
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002729 conn = objt_conn(l4->si[0].end);
2730 if (!conn || conn->xprt != &ssl_sock)
2731 return 0;
2732
2733 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002734 smp->flags = SMP_F_MAY_CHANGE;
2735 return 0;
2736 }
2737
2738 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002739 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002740 smp->flags = 0;
2741
2742 return 1;
2743}
2744
Emeric Brun2525b6b2012-10-18 15:59:43 +02002745/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002746static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002747smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002748 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002749{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002750 struct connection *conn;
2751
2752 if (!l4)
2753 return 0;
2754
2755 conn = objt_conn(l4->si[0].end);
2756 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002757 return 0;
2758
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002759 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002760 smp->flags = SMP_F_MAY_CHANGE;
2761 return 0;
2762 }
2763
2764 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002765 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002766 smp->flags = 0;
2767
2768 return 1;
2769}
2770
Emeric Brun2525b6b2012-10-18 15:59:43 +02002771/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002772static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002773smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002774 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002775{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002776 struct connection *conn;
2777
2778 if (!l4)
Emeric Brunf282a812012-09-21 15:27:54 +02002779 return 0;
2780
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002781 conn = objt_conn(l4->si[0].end);
2782 if (!conn || conn->xprt != &ssl_sock)
2783 return 0;
2784
2785 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002786 smp->flags = SMP_F_MAY_CHANGE;
2787 return 0;
2788 }
2789
2790 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002791 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002792 smp->flags = 0;
2793
2794 return 1;
2795}
2796
Emeric Brun2525b6b2012-10-18 15:59:43 +02002797/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002798static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002799smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002800 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002801{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002802 struct connection *conn;
2803
2804 if (!l4)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002805 return 0;
2806
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002807 conn = objt_conn(l4->si[0].end);
2808 if (!conn || conn->xprt != &ssl_sock)
2809 return 0;
2810
2811 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002812 smp->flags = SMP_F_MAY_CHANGE;
2813 return 0;
2814 }
2815
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002816 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002817 return 0;
2818
2819 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002820 smp->data.uint = (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002821 smp->flags = 0;
2822
2823 return 1;
2824}
2825
Emeric Brunfb510ea2012-10-05 12:00:26 +02002826/* parse the "ca-file" bind keyword */
2827static 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 +02002828{
2829 if (!*args[cur_arg + 1]) {
2830 if (err)
2831 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2832 return ERR_ALERT | ERR_FATAL;
2833 }
2834
Emeric Brunef42d922012-10-11 16:11:36 +02002835 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2836 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2837 else
2838 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002839
Emeric Brund94b3fe2012-09-20 18:23:56 +02002840 return 0;
2841}
2842
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002843/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002844static 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 +02002845{
2846 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002847 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002848 return ERR_ALERT | ERR_FATAL;
2849 }
2850
Emeric Brun76d88952012-10-05 15:47:31 +02002851 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002852 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002853 return 0;
2854}
2855
2856/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002857static 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 +02002858{
Willy Tarreau38011032013-08-13 16:59:39 +02002859 char path[MAXPATHLEN];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002860 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002861 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002862 return ERR_ALERT | ERR_FATAL;
2863 }
2864
Emeric Brunc8e8d122012-10-02 18:42:10 +02002865 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
Willy Tarreau38011032013-08-13 16:59:39 +02002866 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02002867 memprintf(err, "'%s' : path too long", args[cur_arg]);
2868 return ERR_ALERT | ERR_FATAL;
2869 }
2870 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2871 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2872 return ERR_ALERT | ERR_FATAL;
2873
2874 return 0;
2875 }
2876
Willy Tarreau4348fad2012-09-20 16:48:07 +02002877 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002878 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002879
2880 return 0;
2881}
2882
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002883/* parse the "crt-list" bind keyword */
2884static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2885{
2886 if (!*args[cur_arg + 1]) {
2887 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
2888 return ERR_ALERT | ERR_FATAL;
2889 }
2890
Willy Tarreauad1731d2013-04-02 17:35:58 +02002891 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
2892 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002893 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02002894 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002895
2896 return 0;
2897}
2898
Emeric Brunfb510ea2012-10-05 12:00:26 +02002899/* parse the "crl-file" bind keyword */
2900static 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 +02002901{
Emeric Brun051cdab2012-10-02 19:25:50 +02002902#ifndef X509_V_FLAG_CRL_CHECK
2903 if (err)
2904 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2905 return ERR_ALERT | ERR_FATAL;
2906#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002907 if (!*args[cur_arg + 1]) {
2908 if (err)
2909 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2910 return ERR_ALERT | ERR_FATAL;
2911 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002912
Emeric Brunef42d922012-10-11 16:11:36 +02002913 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2914 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2915 else
2916 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002917
Emeric Brun2b58d042012-09-20 17:10:03 +02002918 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002919#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002920}
2921
2922/* parse the "ecdhe" bind keyword keywords */
2923static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2924{
2925#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2926 if (err)
2927 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2928 return ERR_ALERT | ERR_FATAL;
2929#elif defined(OPENSSL_NO_ECDH)
2930 if (err)
2931 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2932 return ERR_ALERT | ERR_FATAL;
2933#else
2934 if (!*args[cur_arg + 1]) {
2935 if (err)
2936 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2937 return ERR_ALERT | ERR_FATAL;
2938 }
2939
2940 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002941
2942 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002943#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002944}
2945
Emeric Brun81c00f02012-09-21 14:31:21 +02002946/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2947static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2948{
2949 int code;
2950 char *p = args[cur_arg + 1];
2951 unsigned long long *ignerr = &conf->crt_ignerr;
2952
2953 if (!*p) {
2954 if (err)
2955 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2956 return ERR_ALERT | ERR_FATAL;
2957 }
2958
2959 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2960 ignerr = &conf->ca_ignerr;
2961
2962 if (strcmp(p, "all") == 0) {
2963 *ignerr = ~0ULL;
2964 return 0;
2965 }
2966
2967 while (p) {
2968 code = atoi(p);
2969 if ((code <= 0) || (code > 63)) {
2970 if (err)
2971 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2972 args[cur_arg], code, args[cur_arg + 1]);
2973 return ERR_ALERT | ERR_FATAL;
2974 }
2975 *ignerr |= 1ULL << code;
2976 p = strchr(p, ',');
2977 if (p)
2978 p++;
2979 }
2980
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002981 return 0;
2982}
2983
2984/* parse the "force-sslv3" bind keyword */
2985static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2986{
2987 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2988 return 0;
2989}
2990
2991/* parse the "force-tlsv10" bind keyword */
2992static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2993{
2994 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002995 return 0;
2996}
2997
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002998/* parse the "force-tlsv11" bind keyword */
2999static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3000{
3001#if SSL_OP_NO_TLSv1_1
3002 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
3003 return 0;
3004#else
3005 if (err)
3006 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
3007 return ERR_ALERT | ERR_FATAL;
3008#endif
3009}
3010
3011/* parse the "force-tlsv12" bind keyword */
3012static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3013{
3014#if SSL_OP_NO_TLSv1_2
3015 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
3016 return 0;
3017#else
3018 if (err)
3019 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
3020 return ERR_ALERT | ERR_FATAL;
3021#endif
3022}
3023
3024
Emeric Brun2d0c4822012-10-02 13:45:20 +02003025/* parse the "no-tls-tickets" bind keyword */
3026static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3027{
Emeric Brun89675492012-10-05 13:48:26 +02003028 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02003029 return 0;
3030}
3031
Emeric Brun2d0c4822012-10-02 13:45:20 +02003032
Emeric Brun9b3009b2012-10-05 11:55:06 +02003033/* parse the "no-sslv3" bind keyword */
3034static 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 +02003035{
Emeric Brun89675492012-10-05 13:48:26 +02003036 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003037 return 0;
3038}
3039
Emeric Brun9b3009b2012-10-05 11:55:06 +02003040/* parse the "no-tlsv10" bind keyword */
3041static 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 +02003042{
Emeric Brun89675492012-10-05 13:48:26 +02003043 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02003044 return 0;
3045}
3046
Emeric Brun9b3009b2012-10-05 11:55:06 +02003047/* parse the "no-tlsv11" bind keyword */
3048static 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 +02003049{
Emeric Brun89675492012-10-05 13:48:26 +02003050 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02003051 return 0;
3052}
3053
Emeric Brun9b3009b2012-10-05 11:55:06 +02003054/* parse the "no-tlsv12" bind keyword */
3055static 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 +02003056{
Emeric Brun89675492012-10-05 13:48:26 +02003057 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003058 return 0;
3059}
3060
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003061/* parse the "npn" bind keyword */
3062static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3063{
3064#ifdef OPENSSL_NPN_NEGOTIATED
3065 char *p1, *p2;
3066
3067 if (!*args[cur_arg + 1]) {
3068 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
3069 return ERR_ALERT | ERR_FATAL;
3070 }
3071
3072 free(conf->npn_str);
3073
3074 /* the NPN string is built as a suite of (<len> <name>)* */
3075 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
3076 conf->npn_str = calloc(1, conf->npn_len);
3077 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
3078
3079 /* replace commas with the name length */
3080 p1 = conf->npn_str;
3081 p2 = p1 + 1;
3082 while (1) {
3083 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
3084 if (!p2)
3085 p2 = p1 + 1 + strlen(p1 + 1);
3086
3087 if (p2 - (p1 + 1) > 255) {
3088 *p2 = '\0';
3089 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
3090 return ERR_ALERT | ERR_FATAL;
3091 }
3092
3093 *p1 = p2 - (p1 + 1);
3094 p1 = p2;
3095
3096 if (!*p2)
3097 break;
3098
3099 *(p2++) = '\0';
3100 }
3101 return 0;
3102#else
3103 if (err)
3104 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
3105 return ERR_ALERT | ERR_FATAL;
3106#endif
3107}
3108
Willy Tarreauab861d32013-04-02 02:30:41 +02003109/* parse the "alpn" bind keyword */
3110static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3111{
3112#ifdef OPENSSL_ALPN_NEGOTIATED
3113 char *p1, *p2;
3114
3115 if (!*args[cur_arg + 1]) {
3116 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
3117 return ERR_ALERT | ERR_FATAL;
3118 }
3119
3120 free(conf->alpn_str);
3121
3122 /* the ALPN string is built as a suite of (<len> <name>)* */
3123 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
3124 conf->alpn_str = calloc(1, conf->alpn_len);
3125 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
3126
3127 /* replace commas with the name length */
3128 p1 = conf->alpn_str;
3129 p2 = p1 + 1;
3130 while (1) {
3131 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
3132 if (!p2)
3133 p2 = p1 + 1 + strlen(p1 + 1);
3134
3135 if (p2 - (p1 + 1) > 255) {
3136 *p2 = '\0';
3137 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
3138 return ERR_ALERT | ERR_FATAL;
3139 }
3140
3141 *p1 = p2 - (p1 + 1);
3142 p1 = p2;
3143
3144 if (!*p2)
3145 break;
3146
3147 *(p2++) = '\0';
3148 }
3149 return 0;
3150#else
3151 if (err)
3152 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
3153 return ERR_ALERT | ERR_FATAL;
3154#endif
3155}
3156
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003157/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003158static 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 +02003159{
Willy Tarreau81796be2012-09-22 19:11:47 +02003160 struct listener *l;
3161
Willy Tarreau4348fad2012-09-20 16:48:07 +02003162 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02003163
3164 if (global.listen_default_ciphers && !conf->ciphers)
3165 conf->ciphers = strdup(global.listen_default_ciphers);
3166
Willy Tarreau81796be2012-09-22 19:11:47 +02003167 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003168 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02003169
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003170 return 0;
3171}
3172
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003173/* parse the "strict-sni" bind keyword */
3174static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3175{
3176 conf->strict_sni = 1;
3177 return 0;
3178}
3179
Emeric Brund94b3fe2012-09-20 18:23:56 +02003180/* parse the "verify" bind keyword */
3181static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3182{
3183 if (!*args[cur_arg + 1]) {
3184 if (err)
3185 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
3186 return ERR_ALERT | ERR_FATAL;
3187 }
3188
3189 if (strcmp(args[cur_arg + 1], "none") == 0)
3190 conf->verify = SSL_VERIFY_NONE;
3191 else if (strcmp(args[cur_arg + 1], "optional") == 0)
3192 conf->verify = SSL_VERIFY_PEER;
3193 else if (strcmp(args[cur_arg + 1], "required") == 0)
3194 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
3195 else {
3196 if (err)
3197 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
3198 args[cur_arg], args[cur_arg + 1]);
3199 return ERR_ALERT | ERR_FATAL;
3200 }
3201
3202 return 0;
3203}
3204
Willy Tarreau92faadf2012-10-10 23:04:25 +02003205/************** "server" keywords ****************/
3206
Emeric Brunef42d922012-10-11 16:11:36 +02003207/* parse the "ca-file" server keyword */
3208static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3209{
3210 if (!*args[*cur_arg + 1]) {
3211 if (err)
3212 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
3213 return ERR_ALERT | ERR_FATAL;
3214 }
3215
3216 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3217 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3218 else
3219 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
3220
3221 return 0;
3222}
3223
Willy Tarreau92faadf2012-10-10 23:04:25 +02003224/* parse the "check-ssl" server keyword */
3225static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3226{
3227 newsrv->check.use_ssl = 1;
3228 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3229 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3230 return 0;
3231}
3232
3233/* parse the "ciphers" server keyword */
3234static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3235{
3236 if (!*args[*cur_arg + 1]) {
3237 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
3238 return ERR_ALERT | ERR_FATAL;
3239 }
3240
3241 free(newsrv->ssl_ctx.ciphers);
3242 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
3243 return 0;
3244}
3245
Emeric Brunef42d922012-10-11 16:11:36 +02003246/* parse the "crl-file" server keyword */
3247static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3248{
3249#ifndef X509_V_FLAG_CRL_CHECK
3250 if (err)
3251 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
3252 return ERR_ALERT | ERR_FATAL;
3253#else
3254 if (!*args[*cur_arg + 1]) {
3255 if (err)
3256 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
3257 return ERR_ALERT | ERR_FATAL;
3258 }
3259
3260 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3261 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3262 else
3263 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
3264
3265 return 0;
3266#endif
3267}
3268
Emeric Bruna7aa3092012-10-26 12:58:00 +02003269/* parse the "crt" server keyword */
3270static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3271{
3272 if (!*args[*cur_arg + 1]) {
3273 if (err)
3274 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
3275 return ERR_ALERT | ERR_FATAL;
3276 }
3277
3278 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
3279 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3280 else
3281 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
3282
3283 return 0;
3284}
Emeric Brunef42d922012-10-11 16:11:36 +02003285
Willy Tarreau92faadf2012-10-10 23:04:25 +02003286/* parse the "force-sslv3" server keyword */
3287static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3288{
3289 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
3290 return 0;
3291}
3292
3293/* parse the "force-tlsv10" server keyword */
3294static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3295{
3296 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
3297 return 0;
3298}
3299
3300/* parse the "force-tlsv11" server keyword */
3301static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3302{
3303#if SSL_OP_NO_TLSv1_1
3304 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
3305 return 0;
3306#else
3307 if (err)
3308 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
3309 return ERR_ALERT | ERR_FATAL;
3310#endif
3311}
3312
3313/* parse the "force-tlsv12" server keyword */
3314static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3315{
3316#if SSL_OP_NO_TLSv1_2
3317 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
3318 return 0;
3319#else
3320 if (err)
3321 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
3322 return ERR_ALERT | ERR_FATAL;
3323#endif
3324}
3325
3326/* parse the "no-sslv3" server keyword */
3327static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3328{
3329 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
3330 return 0;
3331}
3332
3333/* parse the "no-tlsv10" server keyword */
3334static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3335{
3336 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
3337 return 0;
3338}
3339
3340/* parse the "no-tlsv11" server keyword */
3341static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3342{
3343 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
3344 return 0;
3345}
3346
3347/* parse the "no-tlsv12" server keyword */
3348static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3349{
3350 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
3351 return 0;
3352}
3353
Emeric Brunf9c5c472012-10-11 15:28:34 +02003354/* parse the "no-tls-tickets" server keyword */
3355static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3356{
3357 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
3358 return 0;
3359}
3360
Willy Tarreau92faadf2012-10-10 23:04:25 +02003361/* parse the "ssl" server keyword */
3362static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3363{
3364 newsrv->use_ssl = 1;
3365 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3366 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3367 return 0;
3368}
3369
Emeric Brunef42d922012-10-11 16:11:36 +02003370/* parse the "verify" server keyword */
3371static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3372{
3373 if (!*args[*cur_arg + 1]) {
3374 if (err)
3375 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
3376 return ERR_ALERT | ERR_FATAL;
3377 }
3378
3379 if (strcmp(args[*cur_arg + 1], "none") == 0)
3380 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
3381 else if (strcmp(args[*cur_arg + 1], "required") == 0)
3382 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
3383 else {
3384 if (err)
3385 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
3386 args[*cur_arg], args[*cur_arg + 1]);
3387 return ERR_ALERT | ERR_FATAL;
3388 }
3389
Evan Broderbe554312013-06-27 00:05:25 -07003390 return 0;
3391}
3392
3393/* parse the "verifyhost" server keyword */
3394static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3395{
3396 if (!*args[*cur_arg + 1]) {
3397 if (err)
3398 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
3399 return ERR_ALERT | ERR_FATAL;
3400 }
3401
3402 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
3403
Emeric Brunef42d922012-10-11 16:11:36 +02003404 return 0;
3405}
3406
Willy Tarreau7875d092012-09-10 08:20:03 +02003407/* Note: must not be declared <const> as its list will be overwritten.
3408 * Please take care of keeping this list alphabetically sorted.
3409 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003410static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Willy Tarreau80aca902013-01-07 15:42:20 +01003411 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3412 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3413 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3414 { "ssl_c_i_dn", smp_fetch_ssl_c_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3415 { "ssl_c_key_alg", smp_fetch_ssl_c_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3416 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3417 { "ssl_c_notbefore", smp_fetch_ssl_c_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3418 { "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3419 { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3420 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
James Votha051b4a2013-05-14 20:37:59 +02003421 { "ssl_c_sha1", smp_fetch_ssl_c_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01003422 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3423 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3424 { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3425 { "ssl_f_i_dn", smp_fetch_ssl_f_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3426 { "ssl_f_key_alg", smp_fetch_ssl_f_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3427 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3428 { "ssl_f_notbefore", smp_fetch_ssl_f_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3429 { "ssl_f_sig_alg", smp_fetch_ssl_f_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3430 { "ssl_f_s_dn", smp_fetch_ssl_f_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3431 { "ssl_f_serial", smp_fetch_ssl_f_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3432 { "ssl_f_version", smp_fetch_ssl_f_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3433 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3434 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3435 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3436 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3437 { "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 +02003438#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau80aca902013-01-07 15:42:20 +01003439 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003440#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003441#ifdef OPENSSL_ALPN_NEGOTIATED
3442 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3443#endif
Willy Tarreau80aca902013-01-07 15:42:20 +01003444 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3445 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3446 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_CBIN, SMP_USE_L5CLI },
3447 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreau7875d092012-09-10 08:20:03 +02003448 { NULL, NULL, 0, 0, 0 },
3449}};
3450
3451/* Note: must not be declared <const> as its list will be overwritten.
3452 * Please take care of keeping this list alphabetically sorted.
3453 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003454static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003455 { "ssl_c_i_dn", NULL, pat_parse_str, pat_match_str },
3456 { "ssl_c_key_alg", NULL, pat_parse_str, pat_match_str },
3457 { "ssl_c_notafter", NULL, pat_parse_str, pat_match_str },
3458 { "ssl_c_notbefore", NULL, pat_parse_str, pat_match_str },
3459 { "ssl_c_sig_alg", NULL, pat_parse_str, pat_match_str },
3460 { "ssl_c_s_dn", NULL, pat_parse_str, pat_match_str },
3461 { "ssl_c_serial", NULL, pat_parse_bin, pat_match_bin },
3462 { "ssl_f_i_dn", NULL, pat_parse_str, pat_match_str },
3463 { "ssl_f_key_alg", NULL, pat_parse_str, pat_match_str },
3464 { "ssl_f_notafter", NULL, pat_parse_str, pat_match_str },
3465 { "ssl_f_notbefore", NULL, pat_parse_str, pat_match_str },
3466 { "ssl_f_sig_alg", NULL, pat_parse_str, pat_match_str },
3467 { "ssl_f_s_dn", NULL, pat_parse_str, pat_match_str },
3468 { "ssl_f_serial", NULL, pat_parse_bin, pat_match_bin },
3469 { "ssl_fc_cipher", NULL, pat_parse_str, pat_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003470#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003471 { "ssl_fc_npn", NULL, pat_parse_str, pat_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003472#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003473#ifdef OPENSSL_ALPN_NEGOTIATED
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003474 { "ssl_fc_alpn", NULL, pat_parse_str, pat_match_str },
Willy Tarreauab861d32013-04-02 02:30:41 +02003475#endif
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003476 { "ssl_fc_protocol", NULL, pat_parse_str, pat_match_str },
3477 { "ssl_fc_sni", "ssl_fc_sni", pat_parse_str, pat_match_str },
3478 { "ssl_fc_sni_end", "ssl_fc_sni", pat_parse_str, pat_match_end },
3479 { "ssl_fc_sni_reg", "ssl_fc_sni", pat_parse_reg, pat_match_reg },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01003480 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02003481}};
3482
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003483/* Note: must not be declared <const> as its list will be overwritten.
3484 * Please take care of keeping this list alphabetically sorted, doing so helps
3485 * all code contributors.
3486 * Optional keywords are also declared with a NULL ->parse() function so that
3487 * the config parser can report an appropriate error when a known keyword was
3488 * not enabled.
3489 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02003490static struct bind_kw_list bind_kws = { "SSL", { }, {
Willy Tarreauab861d32013-04-02 02:30:41 +02003491 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003492 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003493 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
3494 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003495 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003496 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
3497 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003498 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003499 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003500 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
3501 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
3502 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
3503 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02003504 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
3505 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
3506 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
3507 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003508 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003509 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003510 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003511 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003512 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003513 { NULL, NULL, 0 },
3514}};
Emeric Brun46591952012-05-18 15:47:34 +02003515
Willy Tarreau92faadf2012-10-10 23:04:25 +02003516/* Note: must not be declared <const> as its list will be overwritten.
3517 * Please take care of keeping this list alphabetically sorted, doing so helps
3518 * all code contributors.
3519 * Optional keywords are also declared with a NULL ->parse() function so that
3520 * the config parser can report an appropriate error when a known keyword was
3521 * not enabled.
3522 */
3523static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02003524 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003525 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
3526 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02003527 { "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 +02003528 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003529 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
3530 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
3531 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
3532 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
3533 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
3534 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
3535 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
3536 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02003537 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003538 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02003539 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Evan Broderbe554312013-06-27 00:05:25 -07003540 { "verifyhost", srv_parse_verifyhost, 1, 0 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02003541 { NULL, NULL, 0, 0 },
3542}};
3543
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003544/* transport-layer operations for SSL sockets */
3545struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02003546 .snd_buf = ssl_sock_from_buf,
3547 .rcv_buf = ssl_sock_to_buf,
3548 .rcv_pipe = NULL,
3549 .snd_pipe = NULL,
3550 .shutr = NULL,
3551 .shutw = ssl_sock_shutw,
3552 .close = ssl_sock_close,
3553 .init = ssl_sock_init,
3554};
3555
3556__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02003557static void __ssl_sock_init(void)
3558{
Emeric Brun46591952012-05-18 15:47:34 +02003559 STACK_OF(SSL_COMP)* cm;
3560
3561 SSL_library_init();
3562 cm = SSL_COMP_get_compression_methods();
3563 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02003564 sample_register_fetches(&sample_fetch_keywords);
3565 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003566 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02003567 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02003568}
3569
3570/*
3571 * Local variables:
3572 * c-indent-level: 8
3573 * c-basic-offset: 8
3574 * End:
3575 */