blob: e84e191b445c658d0b48a64624361f73c88a5f40 [file] [log] [blame]
Emeric Brun46591952012-05-18 15:47:34 +02001/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02003 *
4 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
Willy Tarreau69845df2012-09-10 09:43:09 +020011 * Acknowledgement:
12 * We'd like to specially thank the Stud project authors for a very clean
13 * and well documented code which helped us understand how the OpenSSL API
14 * ought to be used in non-blocking mode. This is one difficult part which
15 * is not easy to get from the OpenSSL doc, and reading the Stud code made
16 * it much more obvious than the examples in the OpenSSL package. Keep up
17 * the good works, guys !
18 *
19 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
20 * particularly well with haproxy. For more info about this project, visit :
21 * https://github.com/bumptech/stud
22 *
Emeric Brun46591952012-05-18 15:47:34 +020023 */
24
25#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020026#include <ctype.h>
27#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020028#include <errno.h>
29#include <fcntl.h>
30#include <stdio.h>
31#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020032#include <string.h>
33#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020034
35#include <sys/socket.h>
36#include <sys/stat.h>
37#include <sys/types.h>
38
39#include <netinet/tcp.h>
40
41#include <openssl/ssl.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020042#include <openssl/x509.h>
43#include <openssl/x509v3.h>
44#include <openssl/x509.h>
45#include <openssl/err.h>
Thierry Fournier383085f2013-01-24 14:15:43 +010046#include <openssl/rand.h>
Emeric Brun46591952012-05-18 15:47:34 +020047
48#include <common/buffer.h>
49#include <common/compat.h>
50#include <common/config.h>
51#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020052#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020053#include <common/standard.h>
54#include <common/ticks.h>
55#include <common/time.h>
56
Emeric Brunfc0421f2012-09-07 17:30:07 +020057#include <ebsttree.h>
58
59#include <types/global.h>
60#include <types/ssl_sock.h>
61
Willy Tarreau7875d092012-09-10 08:20:03 +020062#include <proto/acl.h>
63#include <proto/arg.h>
Emeric Brun46591952012-05-18 15:47:34 +020064#include <proto/connection.h>
65#include <proto/fd.h>
66#include <proto/freq_ctr.h>
67#include <proto/frontend.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020068#include <proto/listener.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010069#include <proto/pattern.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020070#include <proto/server.h>
Emeric Brun46591952012-05-18 15:47:34 +020071#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +020072#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020073#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +020074#include <proto/ssl_sock.h>
75#include <proto/task.h>
76
Emeric Brune64aef12012-09-21 13:15:06 +020077#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brunf282a812012-09-21 15:27:54 +020078/* bits 0xFFFF0000 are reserved to store verify errors */
79
80/* Verify errors macros */
81#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
82#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
83#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
84
85#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
86#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
87#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +020088
Willy Tarreau403edff2012-09-06 11:58:37 +020089static int sslconns = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +020090
91void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
92{
93 struct connection *conn = (struct connection *)SSL_get_app_data(ssl);
94 (void)ret; /* shut gcc stupid warning */
95
96 if (where & SSL_CB_HANDSHAKE_START) {
97 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreau20879a02012-12-03 16:32:10 +010098 if (conn->flags & CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +020099 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +0100100 conn->err_code = CO_ER_SSL_RENEG;
101 }
Emeric Brune1f38db2012-09-03 20:36:47 +0200102 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200103}
104
Emeric Brune64aef12012-09-21 13:15:06 +0200105/* Callback is called for each certificate of the chain during a verify
106 ok is set to 1 if preverify detect no error on current certificate.
107 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -0700108int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +0200109{
110 SSL *ssl;
111 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +0200112 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +0200113
114 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
115 conn = (struct connection *)SSL_get_app_data(ssl);
116
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200117 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +0200118
Emeric Brun81c00f02012-09-21 14:31:21 +0200119 if (ok) /* no errors */
120 return ok;
121
122 depth = X509_STORE_CTX_get_error_depth(x_store);
123 err = X509_STORE_CTX_get_error(x_store);
124
125 /* check if CA error needs to be ignored */
126 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200127 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
128 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
129 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +0200130 }
131
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100132 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
133 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +0200134 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100135 }
Emeric Brun81c00f02012-09-21 14:31:21 +0200136
Willy Tarreau20879a02012-12-03 16:32:10 +0100137 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +0200138 return 0;
139 }
140
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200141 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
142 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +0200143
Emeric Brun81c00f02012-09-21 14:31:21 +0200144 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100145 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
146 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +0200147 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100148 }
Emeric Brun81c00f02012-09-21 14:31:21 +0200149
Willy Tarreau20879a02012-12-03 16:32:10 +0100150 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +0200151 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +0200152}
153
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200154#ifdef OPENSSL_NPN_NEGOTIATED
155/* This callback is used so that the server advertises the list of
156 * negociable protocols for NPN.
157 */
158static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
159 unsigned int *len, void *arg)
160{
161 struct bind_conf *conf = arg;
162
163 *data = (const unsigned char *)conf->npn_str;
164 *len = conf->npn_len;
165 return SSL_TLSEXT_ERR_OK;
166}
167#endif
168
Willy Tarreauab861d32013-04-02 02:30:41 +0200169#ifdef OPENSSL_ALPN_NEGOTIATED
170/* This callback is used so that the server advertises the list of
171 * negociable protocols for ALPN.
172 */
173static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **data,
174 unsigned int *len, void *arg)
175{
176 struct bind_conf *conf = arg;
177
178 *data = (const unsigned char *)conf->alpn_str;
179 *len = conf->alpn_len;
180 return SSL_TLSEXT_ERR_OK;
181}
182#endif
183
Emeric Brunfc0421f2012-09-07 17:30:07 +0200184#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
185/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
186 * warning when no match is found, which implies the default (first) cert
187 * will keep being used.
188 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200189static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, struct bind_conf *s)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200190{
191 const char *servername;
192 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200193 struct ebmb_node *node, *n;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200194 int i;
195 (void)al; /* shut gcc stupid warning */
196
197 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100198 if (!servername) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200199 return (s->strict_sni ?
200 SSL_TLSEXT_ERR_ALERT_FATAL :
Emmanuel Hocdet79274e22013-05-31 12:47:44 +0200201 SSL_TLSEXT_ERR_NOACK);
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100202 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200203
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100204 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200205 if (!servername[i])
206 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100207 trash.str[i] = tolower(servername[i]);
208 if (!wildp && (trash.str[i] == '.'))
209 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200210 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100211 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200212
213 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100214 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200215
216 /* lookup a not neg filter */
217 for (n = node; n; n = ebmb_next_dup(n)) {
218 if (!container_of(n, struct sni_ctx, name)->neg) {
219 node = n;
220 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100221 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200222 }
223 if (!node && wildp) {
224 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +0200225 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200226 }
227 if (!node || container_of(node, struct sni_ctx, name)->neg) {
228 return (s->strict_sni ?
229 SSL_TLSEXT_ERR_ALERT_FATAL :
230 SSL_TLSEXT_ERR_ALERT_WARNING);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200231 }
232
233 /* switch ctx */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200234 SSL_set_SSL_CTX(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200235 return SSL_TLSEXT_ERR_OK;
236}
237#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
238
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200239#ifndef OPENSSL_NO_DH
240/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
241 if an error occured, and 0 if parameter not found. */
242int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
243{
244 int ret = -1;
245 BIO *in;
246 DH *dh = NULL;
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200247 /* If not present, use parameters generated using 'openssl dhparam 1024 -C':
248 * -----BEGIN DH PARAMETERS-----
249 * MIGHAoGBAJJAJDXDoS5E03MNjnjK36eOL1tRqVa/9NuOVlI+lpXmPjJQbP65EvKn
250 * fSLnG7VMhoCJO4KtG88zf393ltP7loGB2bofcDSr+x+XsxBM8yA/Zj6BmQt+CQ9s
251 * TF7hoOV+wXTT6ErZ5y5qx9pq6hLfKXwTGFT78hrE6HnCO7xgtPdTAgEC
252 * -----END DH PARAMETERS-----
253 */
254 static const unsigned char dh1024_p[] = {
255 0x92, 0x40, 0x24, 0x35, 0xC3, 0xA1, 0x2E, 0x44, 0xD3, 0x73, 0x0D, 0x8E,
256 0x78, 0xCA, 0xDF, 0xA7, 0x8E, 0x2F, 0x5B, 0x51, 0xA9, 0x56, 0xBF, 0xF4,
257 0xDB, 0x8E, 0x56, 0x52, 0x3E, 0x96, 0x95, 0xE6, 0x3E, 0x32, 0x50, 0x6C,
258 0xFE, 0xB9, 0x12, 0xF2, 0xA7, 0x7D, 0x22, 0xE7, 0x1B, 0xB5, 0x4C, 0x86,
259 0x80, 0x89, 0x3B, 0x82, 0xAD, 0x1B, 0xCF, 0x33, 0x7F, 0x7F, 0x77, 0x96,
260 0xD3, 0xFB, 0x96, 0x81, 0x81, 0xD9, 0xBA, 0x1F, 0x70, 0x34, 0xAB, 0xFB,
261 0x1F, 0x97, 0xB3, 0x10, 0x4C, 0xF3, 0x20, 0x3F, 0x66, 0x3E, 0x81, 0x99,
262 0x0B, 0x7E, 0x09, 0x0F, 0x6C, 0x4C, 0x5E, 0xE1, 0xA0, 0xE5, 0x7E, 0xC1,
263 0x74, 0xD3, 0xE8, 0x4A, 0xD9, 0xE7, 0x2E, 0x6A, 0xC7, 0xDA, 0x6A, 0xEA,
264 0x12, 0xDF, 0x29, 0x7C, 0x13, 0x18, 0x54, 0xFB, 0xF2, 0x1A, 0xC4, 0xE8,
265 0x79, 0xC2, 0x3B, 0xBC, 0x60, 0xB4, 0xF7, 0x53,
266 };
267 static const unsigned char dh1024_g[] = {
268 0x02,
269 };
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200270
271 in = BIO_new(BIO_s_file());
272 if (in == NULL)
273 goto end;
274
275 if (BIO_read_filename(in, file) <= 0)
276 goto end;
277
278 dh = PEM_read_bio_DHparams(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200279 if (!dh) {
280 /* Clear openssl global errors stack */
281 ERR_clear_error();
282
283 dh = DH_new();
284 if (dh == NULL)
285 goto end;
286
287 dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
288 if (dh->p == NULL)
289 goto end;
290
291 dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
292 if (dh->g == NULL)
293 goto end;
294
295 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200296 }
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200297 else
298 ret = 1;
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200299
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200300 SSL_CTX_set_tmp_dh(ctx, dh);
Emeric Brun644cde02012-12-14 11:21:13 +0100301
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200302end:
303 if (dh)
304 DH_free(dh);
305
306 if (in)
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200307 BIO_free(in);
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200308
309 return ret;
310}
311#endif
312
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200313static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100314{
315 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200316 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100317
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200318 if (*name == '!') {
319 neg = 1;
320 name++;
321 }
322 if (*name == '*') {
323 wild = 1;
324 name++;
325 }
326 /* !* filter is a nop */
327 if (neg && wild)
328 return order;
329 if (*name) {
330 int j, len;
331 len = strlen(name);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100332 sc = malloc(sizeof(struct sni_ctx) + len + 1);
333 for (j = 0; j < len; j++)
334 sc->name.key[j] = tolower(name[j]);
335 sc->name.key[len] = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100336 sc->ctx = ctx;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200337 sc->order = order++;
338 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100339 if (wild)
340 ebst_insert(&s->sni_w_ctx, &sc->name);
341 else
342 ebst_insert(&s->sni_ctx, &sc->name);
343 }
344 return order;
345}
346
Emeric Brunfc0421f2012-09-07 17:30:07 +0200347/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
348 * an early error happens and the caller must call SSL_CTX_free() by itelf.
349 */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200350static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200351{
352 BIO *in;
353 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200354 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200355 int ret = -1;
356 int order = 0;
357 X509_NAME *xname;
358 char *str;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200359#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
360 STACK_OF(GENERAL_NAME) *names;
361#endif
362
363 in = BIO_new(BIO_s_file());
364 if (in == NULL)
365 goto end;
366
367 if (BIO_read_filename(in, file) <= 0)
368 goto end;
369
370 x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
371 if (x == NULL)
372 goto end;
373
Emeric Brun50bcecc2013-04-22 13:05:23 +0200374 if (fcount) {
375 while (fcount--)
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200376 order = ssl_sock_add_cert_sni(ctx, s, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100377 }
378 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200379#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100380 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
381 if (names) {
382 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
383 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
384 if (name->type == GEN_DNS) {
385 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200386 order = ssl_sock_add_cert_sni(ctx, s, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100387 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200388 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200389 }
390 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100391 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200392 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200393#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100394 xname = X509_get_subject_name(x);
395 i = -1;
396 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
397 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
398 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200399 order = ssl_sock_add_cert_sni(ctx, s, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100400 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200401 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200402 }
403 }
404
405 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
406 if (!SSL_CTX_use_certificate(ctx, x))
407 goto end;
408
409 if (ctx->extra_certs != NULL) {
410 sk_X509_pop_free(ctx->extra_certs, X509_free);
411 ctx->extra_certs = NULL;
412 }
413
414 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata))) {
415 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
416 X509_free(ca);
417 goto end;
418 }
419 }
420
421 err = ERR_get_error();
422 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
423 /* we successfully reached the last cert in the file */
424 ret = 1;
425 }
426 ERR_clear_error();
427
428end:
429 if (x)
430 X509_free(x);
431
432 if (in)
433 BIO_free(in);
434
435 return ret;
436}
437
Emeric Brun50bcecc2013-04-22 13:05:23 +0200438static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200439{
440 int ret;
441 SSL_CTX *ctx;
442
443 ctx = SSL_CTX_new(SSLv23_server_method());
444 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200445 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
446 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200447 return 1;
448 }
449
450 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200451 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
452 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200453 SSL_CTX_free(ctx);
454 return 1;
455 }
456
Emeric Brun50bcecc2013-04-22 13:05:23 +0200457 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200458 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200459 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
460 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200461 if (ret < 0) /* serious error, must do that ourselves */
462 SSL_CTX_free(ctx);
463 return 1;
464 }
Emeric Brun61694ab2012-10-26 13:35:33 +0200465
466 if (SSL_CTX_check_private_key(ctx) <= 0) {
467 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
468 err && *err ? *err : "", path);
469 return 1;
470 }
471
Emeric Brunfc0421f2012-09-07 17:30:07 +0200472 /* we must not free the SSL_CTX anymore below, since it's already in
473 * the tree, so it will be discovered and cleaned in time.
474 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200475#ifndef OPENSSL_NO_DH
476 ret = ssl_sock_load_dh_params(ctx, path);
477 if (ret < 0) {
478 if (err)
479 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
480 *err ? *err : "", path);
481 return 1;
482 }
483#endif
484
Emeric Brunfc0421f2012-09-07 17:30:07 +0200485#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200486 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200487 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
488 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +0200489 return 1;
490 }
491#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200492 if (!bind_conf->default_ctx)
493 bind_conf->default_ctx = ctx;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200494
495 return 0;
496}
497
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200498int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200499{
500 struct dirent *de;
501 DIR *dir;
502 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +0100503 char *end;
504 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200505 int cfgerr = 0;
506
507 if (!(dir = opendir(path)))
Emeric Brun50bcecc2013-04-22 13:05:23 +0200508 return ssl_sock_load_cert_file(path, bind_conf, curproxy, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200509
510 /* strip trailing slashes, including first one */
511 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
512 *end = 0;
513
Emeric Brunfc0421f2012-09-07 17:30:07 +0200514 while ((de = readdir(dir))) {
Willy Tarreauee2663b2012-12-06 11:36:59 +0100515 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200516 if (stat(fp, &buf) != 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200517 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
518 err && *err ? *err : "", fp, strerror(errno));
Emeric Brunfc0421f2012-09-07 17:30:07 +0200519 cfgerr++;
520 continue;
521 }
522 if (!S_ISREG(buf.st_mode))
523 continue;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200524 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, curproxy, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200525 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200526 closedir(dir);
527 return cfgerr;
528}
529
Thierry Fournier383085f2013-01-24 14:15:43 +0100530/* Make sure openssl opens /dev/urandom before the chroot. The work is only
531 * done once. Zero is returned if the operation fails. No error is returned
532 * if the random is said as not implemented, because we expect that openssl
533 * will use another method once needed.
534 */
535static int ssl_initialize_random()
536{
537 unsigned char random;
538 static int random_initialized = 0;
539
540 if (!random_initialized && RAND_bytes(&random, 1) != 0)
541 random_initialized = 1;
542
543 return random_initialized;
544}
545
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100546int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
547{
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200548 char thisline[LINESIZE];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100549 FILE *f;
550 int linenum = 0;
551 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100552
Willy Tarreauad1731d2013-04-02 17:35:58 +0200553 if ((f = fopen(file, "r")) == NULL) {
554 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100555 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200556 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100557
558 while (fgets(thisline, sizeof(thisline), f) != NULL) {
559 int arg;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200560 int newarg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100561 char *end;
562 char *args[MAX_LINE_ARGS + 1];
563 char *line = thisline;
564
565 linenum++;
566 end = line + strlen(line);
567 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
568 /* Check if we reached the limit and the last char is not \n.
569 * Watch out for the last line without the terminating '\n'!
570 */
Willy Tarreauad1731d2013-04-02 17:35:58 +0200571 memprintf(err, "line %d too long in file '%s', limit is %d characters",
572 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100573 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200574 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100575 }
576
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100577 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200578 newarg = 1;
579 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100580 if (*line == '#' || *line == '\n' || *line == '\r') {
581 /* end of string, end of loop */
582 *line = 0;
583 break;
584 }
585 else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +0200586 newarg = 1;
587 *line = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100588 }
Emeric Brun50bcecc2013-04-22 13:05:23 +0200589 else if (newarg) {
590 if (arg == MAX_LINE_ARGS) {
591 memprintf(err, "too many args on line %d in file '%s'.",
592 linenum, file);
593 cfgerr = 1;
594 break;
595 }
596 newarg = 0;
597 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100598 }
Emeric Brun50bcecc2013-04-22 13:05:23 +0200599 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100600 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200601 if (cfgerr)
602 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200603
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100604 /* empty line */
Emeric Brun50bcecc2013-04-22 13:05:23 +0200605 if (!arg)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100606 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100607
Emeric Brun50bcecc2013-04-22 13:05:23 +0200608 cfgerr = ssl_sock_load_cert_file(args[0], bind_conf, curproxy, &args[1], arg-1, err);
Willy Tarreauad1731d2013-04-02 17:35:58 +0200609 if (cfgerr) {
610 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100611 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200612 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100613 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100614 fclose(f);
615 return cfgerr;
616}
617
Emeric Brunfc0421f2012-09-07 17:30:07 +0200618#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
619#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
620#endif
621
622#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
623#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
Willy Tarreau7d588ee2012-11-26 18:47:31 +0100624#define SSL_renegotiate_pending(arg) 0
Emeric Brunfc0421f2012-09-07 17:30:07 +0200625#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200626#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
627#define SSL_OP_SINGLE_ECDH_USE 0
628#endif
Emeric Brun2d0c4822012-10-02 13:45:20 +0200629#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
630#define SSL_OP_NO_TICKET 0
631#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200632#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
633#define SSL_OP_NO_COMPRESSION 0
634#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +0200635#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
636#define SSL_OP_NO_TLSv1_1 0
637#endif
638#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
639#define SSL_OP_NO_TLSv1_2 0
640#endif
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200641#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
642#define SSL_OP_SINGLE_DH_USE 0
643#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200644#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
645#define SSL_OP_SINGLE_ECDH_USE 0
646#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200647#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
648#define SSL_MODE_RELEASE_BUFFERS 0
649#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200650int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy *curproxy)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200651{
652 int cfgerr = 0;
653 int ssloptions =
654 SSL_OP_ALL | /* all known workarounds for bugs */
655 SSL_OP_NO_SSLv2 |
656 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200657 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +0200658 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +0200659 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
660 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200661 int sslmode =
662 SSL_MODE_ENABLE_PARTIAL_WRITE |
663 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
664 SSL_MODE_RELEASE_BUFFERS;
665
Thierry Fournier383085f2013-01-24 14:15:43 +0100666 /* Make sure openssl opens /dev/urandom before the chroot */
667 if (!ssl_initialize_random()) {
668 Alert("OpenSSL random data generator initialization failed.\n");
669 cfgerr++;
670 }
671
Emeric Brun89675492012-10-05 13:48:26 +0200672 if (bind_conf->ssl_options & BC_SSL_O_NO_SSLV3)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200673 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brun89675492012-10-05 13:48:26 +0200674 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV10)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200675 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun89675492012-10-05 13:48:26 +0200676 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV11)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200677 ssloptions |= SSL_OP_NO_TLSv1_1;
Emeric Brun89675492012-10-05 13:48:26 +0200678 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV12)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200679 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun89675492012-10-05 13:48:26 +0200680 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
Emeric Brun2d0c4822012-10-02 13:45:20 +0200681 ssloptions |= SSL_OP_NO_TICKET;
Emeric Brun2cb7ae52012-10-05 14:14:21 +0200682 if (bind_conf->ssl_options & BC_SSL_O_USE_SSLV3)
683 SSL_CTX_set_ssl_version(ctx, SSLv3_server_method());
684 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV10)
685 SSL_CTX_set_ssl_version(ctx, TLSv1_server_method());
686#if SSL_OP_NO_TLSv1_1
687 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV11)
688 SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method());
689#endif
690#if SSL_OP_NO_TLSv1_2
691 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV12)
692 SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method());
693#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200694
695 SSL_CTX_set_options(ctx, ssloptions);
696 SSL_CTX_set_mode(ctx, sslmode);
Evan Broderbe554312013-06-27 00:05:25 -0700697 SSL_CTX_set_verify(ctx, bind_conf->verify ? bind_conf->verify : SSL_VERIFY_NONE, ssl_sock_bind_verifycbk);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200698 if (bind_conf->verify & SSL_VERIFY_PEER) {
Emeric Brunfb510ea2012-10-05 12:00:26 +0200699 if (bind_conf->ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200700 /* load CAfile to verify */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200701 if (!SSL_CTX_load_verify_locations(ctx, bind_conf->ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200702 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200703 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200704 cfgerr++;
705 }
706 /* set CA names fo client cert request, function returns void */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200707 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(bind_conf->ca_file));
Emeric Brund94b3fe2012-09-20 18:23:56 +0200708 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200709#ifdef X509_V_FLAG_CRL_CHECK
Emeric Brunfb510ea2012-10-05 12:00:26 +0200710 if (bind_conf->crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200711 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
712
Emeric Brunfb510ea2012-10-05 12:00:26 +0200713 if (!store || !X509_STORE_load_locations(store, bind_conf->crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200714 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200715 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200716 cfgerr++;
717 }
Emeric Brun561e5742012-10-02 15:20:55 +0200718 else {
719 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
720 }
Emeric Brund94b3fe2012-09-20 18:23:56 +0200721 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200722#endif
Emeric Brun644cde02012-12-14 11:21:13 +0100723 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +0200724 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200725
Emeric Brun4f65bff2012-11-16 15:11:00 +0100726 if (global.tune.ssllifetime)
727 SSL_CTX_set_timeout(ctx, global.tune.ssllifetime);
728
Emeric Brunfc0421f2012-09-07 17:30:07 +0200729 shared_context_set_cache(ctx);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200730 if (bind_conf->ciphers &&
731 !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200732 Alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200733 curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200734 cfgerr++;
735 }
736
737 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200738#ifdef OPENSSL_NPN_NEGOTIATED
739 if (bind_conf->npn_str)
740 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
741#endif
Willy Tarreauab861d32013-04-02 02:30:41 +0200742#ifdef OPENSSL_ALPN_NEGOTIATED
743 if (bind_conf->alpn_str)
744 SSL_CTX_set_alpn_advertised_cb(ctx, ssl_sock_advertise_alpn_protos, bind_conf);
745#endif
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200746
Emeric Brunfc0421f2012-09-07 17:30:07 +0200747#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
748 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200749 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200750#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200751#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emeric Brun6924ef82013-03-06 14:08:53 +0100752 {
Emeric Brun2b58d042012-09-20 17:10:03 +0200753 int i;
754 EC_KEY *ecdh;
755
Emeric Brun6924ef82013-03-06 14:08:53 +0100756 i = OBJ_sn2nid(bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE);
Emeric Brun2b58d042012-09-20 17:10:03 +0200757 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
758 Alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
Emeric Brun6924ef82013-03-06 14:08:53 +0100759 curproxy->id, bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE,
760 bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +0200761 cfgerr++;
762 }
763 else {
764 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
765 EC_KEY_free(ecdh);
766 }
767 }
768#endif
769
Emeric Brunfc0421f2012-09-07 17:30:07 +0200770 return cfgerr;
771}
772
Evan Broderbe554312013-06-27 00:05:25 -0700773static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
774{
775 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
776 size_t prefixlen, suffixlen;
777
778 /* Trivial case */
779 if (strcmp(pattern, hostname) == 0)
780 return 1;
781
Evan Broderbe554312013-06-27 00:05:25 -0700782 /* The rest of this logic is based on RFC 6125, section 6.4.3
783 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
784
Emeric Bruna848dae2013-10-08 11:27:28 +0200785 pattern_wildcard = NULL;
786 pattern_left_label_end = pattern;
787 while (*pattern_left_label_end != '.') {
788 switch (*pattern_left_label_end) {
789 case 0:
790 /* End of label not found */
791 return 0;
792 case '*':
793 /* If there is more than one wildcards */
794 if (pattern_wildcard)
795 return 0;
796 pattern_wildcard = pattern_left_label_end;
797 break;
798 }
799 pattern_left_label_end++;
800 }
801
802 /* If it's not trivial and there is no wildcard, it can't
803 * match */
804 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -0700805 return 0;
806
807 /* Make sure all labels match except the leftmost */
808 hostname_left_label_end = strchr(hostname, '.');
809 if (!hostname_left_label_end
810 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
811 return 0;
812
813 /* Make sure the leftmost label of the hostname is long enough
814 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +0200815 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -0700816 return 0;
817
818 /* Finally compare the string on either side of the
819 * wildcard */
820 prefixlen = pattern_wildcard - pattern;
821 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +0200822 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
823 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -0700824 return 0;
825
826 return 1;
827}
828
829static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
830{
831 SSL *ssl;
832 struct connection *conn;
833 char *servername;
834
835 int depth;
836 X509 *cert;
837 STACK_OF(GENERAL_NAME) *alt_names;
838 int i;
839 X509_NAME *cert_subject;
840 char *str;
841
842 if (ok == 0)
843 return ok;
844
845 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
846 conn = (struct connection *)SSL_get_app_data(ssl);
847
848 servername = objt_server(conn->target)->ssl_ctx.verify_host;
849
850 /* We only need to verify the CN on the actual server cert,
851 * not the indirect CAs */
852 depth = X509_STORE_CTX_get_error_depth(ctx);
853 if (depth != 0)
854 return ok;
855
856 /* At this point, the cert is *not* OK unless we can find a
857 * hostname match */
858 ok = 0;
859
860 cert = X509_STORE_CTX_get_current_cert(ctx);
861 /* It seems like this might happen if verify peer isn't set */
862 if (!cert)
863 return ok;
864
865 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
866 if (alt_names) {
867 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
868 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
869 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +0200870#if OPENSSL_VERSION_NUMBER < 0x00907000L
871 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
872#else
Evan Broderbe554312013-06-27 00:05:25 -0700873 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +0200874#endif
Evan Broderbe554312013-06-27 00:05:25 -0700875 ok = ssl_sock_srv_hostcheck(str, servername);
876 OPENSSL_free(str);
877 }
878 }
879 }
Emeric Brun4ad50a42013-09-17 15:19:54 +0200880 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -0700881 }
882
883 cert_subject = X509_get_subject_name(cert);
884 i = -1;
885 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
886 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
887 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
888 ok = ssl_sock_srv_hostcheck(str, servername);
889 OPENSSL_free(str);
890 }
891 }
892
893 return ok;
894}
895
Emeric Brun94324a42012-10-11 14:00:19 +0200896/* prepare ssl context from servers options. Returns an error count */
897int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
898{
899 int cfgerr = 0;
900 int options =
901 SSL_OP_ALL | /* all known workarounds for bugs */
902 SSL_OP_NO_SSLv2 |
903 SSL_OP_NO_COMPRESSION;
904 int mode =
905 SSL_MODE_ENABLE_PARTIAL_WRITE |
906 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
907 SSL_MODE_RELEASE_BUFFERS;
908
Thierry Fournier383085f2013-01-24 14:15:43 +0100909 /* Make sure openssl opens /dev/urandom before the chroot */
910 if (!ssl_initialize_random()) {
911 Alert("OpenSSL random data generator initialization failed.\n");
912 cfgerr++;
913 }
914
Emeric Brun94324a42012-10-11 14:00:19 +0200915 /* Initiate SSL context for current server */
916 srv->ssl_ctx.reused_sess = NULL;
917 if (srv->use_ssl)
918 srv->xprt = &ssl_sock;
919 if (srv->check.use_ssl)
Simon Horman66183002013-02-23 10:16:43 +0900920 srv->check_common.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +0200921
922 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
923 if (!srv->ssl_ctx.ctx) {
924 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
925 proxy_type_str(curproxy), curproxy->id,
926 srv->id);
927 cfgerr++;
928 return cfgerr;
929 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200930 if (srv->ssl_ctx.client_crt) {
931 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
932 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
933 proxy_type_str(curproxy), curproxy->id,
934 srv->id, srv->ssl_ctx.client_crt);
935 cfgerr++;
936 }
937 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
938 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
939 proxy_type_str(curproxy), curproxy->id,
940 srv->id, srv->ssl_ctx.client_crt);
941 cfgerr++;
942 }
943 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
944 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
945 proxy_type_str(curproxy), curproxy->id,
946 srv->id, srv->ssl_ctx.client_crt);
947 cfgerr++;
948 }
949 }
Emeric Brun94324a42012-10-11 14:00:19 +0200950
951 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
952 options |= SSL_OP_NO_SSLv3;
953 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
954 options |= SSL_OP_NO_TLSv1;
955 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
956 options |= SSL_OP_NO_TLSv1_1;
957 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
958 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200959 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
960 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200961 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
962 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
963 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
964 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
965#if SSL_OP_NO_TLSv1_1
966 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
967 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
968#endif
969#if SSL_OP_NO_TLSv1_2
970 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
971 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
972#endif
973
974 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
975 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Evan Broderbe554312013-06-27 00:05:25 -0700976 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
977 srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE,
978 srv->ssl_ctx.verify_host ? ssl_sock_srv_verifycbk : NULL);
Emeric Brunef42d922012-10-11 16:11:36 +0200979 if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
980 if (srv->ssl_ctx.ca_file) {
981 /* load CAfile to verify */
982 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
983 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
984 curproxy->id, srv->id,
985 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
986 cfgerr++;
987 }
988 }
989#ifdef X509_V_FLAG_CRL_CHECK
990 if (srv->ssl_ctx.crl_file) {
991 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
992
993 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
994 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
995 curproxy->id, srv->id,
996 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
997 cfgerr++;
998 }
999 else {
1000 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
1001 }
1002 }
1003#endif
1004 }
1005
Emeric Brun4f65bff2012-11-16 15:11:00 +01001006 if (global.tune.ssllifetime)
1007 SSL_CTX_set_timeout(srv->ssl_ctx.ctx, global.tune.ssllifetime);
1008
Emeric Brun94324a42012-10-11 14:00:19 +02001009 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
1010 if (srv->ssl_ctx.ciphers &&
1011 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
1012 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
1013 curproxy->id, srv->id,
1014 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
1015 cfgerr++;
1016 }
1017
1018 return cfgerr;
1019}
1020
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001021/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02001022 * be NULL, in which case nothing is done. Returns the number of errors
1023 * encountered.
1024 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001025int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001026{
1027 struct ebmb_node *node;
1028 struct sni_ctx *sni;
1029 int err = 0;
1030
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001031 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001032 return 0;
1033
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001034 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001035 while (node) {
1036 sni = ebmb_entry(node, struct sni_ctx, name);
1037 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001038 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001039 node = ebmb_next(node);
1040 }
1041
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001042 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001043 while (node) {
1044 sni = ebmb_entry(node, struct sni_ctx, name);
1045 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001046 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001047 node = ebmb_next(node);
1048 }
1049 return err;
1050}
1051
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001052/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02001053 * be NULL, in which case nothing is done. The default_ctx is nullified too.
1054 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001055void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001056{
1057 struct ebmb_node *node, *back;
1058 struct sni_ctx *sni;
1059
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001060 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001061 return;
1062
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001063 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001064 while (node) {
1065 sni = ebmb_entry(node, struct sni_ctx, name);
1066 back = ebmb_next(node);
1067 ebmb_delete(node);
1068 if (!sni->order) /* only free the CTX on its first occurrence */
1069 SSL_CTX_free(sni->ctx);
1070 free(sni);
1071 node = back;
1072 }
1073
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001074 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001075 while (node) {
1076 sni = ebmb_entry(node, struct sni_ctx, name);
1077 back = ebmb_next(node);
1078 ebmb_delete(node);
1079 if (!sni->order) /* only free the CTX on its first occurrence */
1080 SSL_CTX_free(sni->ctx);
1081 free(sni);
1082 node = back;
1083 }
1084
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001085 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02001086}
1087
Emeric Brun46591952012-05-18 15:47:34 +02001088/*
1089 * This function is called if SSL * context is not yet allocated. The function
1090 * is designed to be called before any other data-layer operation and sets the
1091 * handshake flag on the connection. It is safe to call it multiple times.
1092 * It returns 0 on success and -1 in error case.
1093 */
1094static int ssl_sock_init(struct connection *conn)
1095{
1096 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001097 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001098 return 0;
1099
Willy Tarreauf79c8172013-10-21 16:30:56 +02001100 if (!(conn->flags & CO_FL_CTRL_READY))
1101 return 0;
1102
Willy Tarreau20879a02012-12-03 16:32:10 +01001103 if (global.maxsslconn && sslconns >= global.maxsslconn) {
1104 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02001105 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001106 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001107
Emeric Brun46591952012-05-18 15:47:34 +02001108 /* If it is in client mode initiate SSL session
1109 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001110 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001111 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001112 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001113 if (!conn->xprt_ctx) {
1114 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001115 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001116 }
Emeric Brun46591952012-05-18 15:47:34 +02001117
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001118 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001119 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1120 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001121
1122 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001123 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001124
Evan Broderbe554312013-06-27 00:05:25 -07001125 /* set connection pointer */
1126 SSL_set_app_data(conn->xprt_ctx, conn);
1127
Emeric Brun46591952012-05-18 15:47:34 +02001128 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001129 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001130
1131 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001132 return 0;
1133 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001134 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001135 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001136 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001137 if (!conn->xprt_ctx) {
1138 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001139 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001140 }
Emeric Brun46591952012-05-18 15:47:34 +02001141
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001142 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001143
1144 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001145 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001146
Emeric Brune1f38db2012-09-03 20:36:47 +02001147 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001148 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +02001149
Emeric Brun46591952012-05-18 15:47:34 +02001150 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001151 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001152
1153 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001154 return 0;
1155 }
1156 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01001157 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02001158 return -1;
1159}
1160
1161
1162/* This is the callback which is used when an SSL handshake is pending. It
1163 * updates the FD status if it wants some polling before being called again.
1164 * It returns 0 if it fails in a fatal way or needs to poll to go further,
1165 * otherwise it returns non-zero and removes itself from the connection's
1166 * flags (the bit is provided in <flag> by the caller).
1167 */
1168int ssl_sock_handshake(struct connection *conn, unsigned int flag)
1169{
1170 int ret;
1171
Willy Tarreauf79c8172013-10-21 16:30:56 +02001172 if (!(conn->flags & CO_FL_CTRL_READY))
1173 return 0;
1174
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001175 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001176 goto out_error;
1177
Emeric Brun674b7432012-11-08 19:21:55 +01001178 /* If we use SSL_do_handshake to process a reneg initiated by
1179 * the remote peer, it sometimes returns SSL_ERROR_SSL.
1180 * Usually SSL_write and SSL_read are used and process implicitly
1181 * the reneg handshake.
1182 * Here we use SSL_peek as a workaround for reneg.
1183 */
1184 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
1185 char c;
1186
1187 ret = SSL_peek(conn->xprt_ctx, &c, 1);
1188 if (ret <= 0) {
1189 /* handshake may have not been completed, let's find why */
1190 ret = SSL_get_error(conn->xprt_ctx, ret);
1191 if (ret == SSL_ERROR_WANT_WRITE) {
1192 /* SSL handshake needs to write, L4 connection may not be ready */
1193 __conn_sock_stop_recv(conn);
1194 __conn_sock_poll_send(conn);
1195 return 0;
1196 }
1197 else if (ret == SSL_ERROR_WANT_READ) {
1198 /* handshake may have been completed but we have
1199 * no more data to read.
1200 */
1201 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
1202 ret = 1;
1203 goto reneg_ok;
1204 }
1205 /* SSL handshake needs to read, L4 connection is ready */
1206 if (conn->flags & CO_FL_WAIT_L4_CONN)
1207 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1208 __conn_sock_stop_send(conn);
1209 __conn_sock_poll_recv(conn);
1210 return 0;
1211 }
1212 else if (ret == SSL_ERROR_SYSCALL) {
1213 /* if errno is null, then connection was successfully established */
1214 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1215 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001216 if (!conn->err_code) {
1217 if (!((SSL *)conn->xprt_ctx)->packet_length)
1218 if (!errno)
1219 conn->err_code = CO_ER_SSL_EMPTY;
1220 else
1221 conn->err_code = CO_ER_SSL_ABORT;
1222 else
1223 conn->err_code = CO_ER_SSL_HANDSHAKE;
1224 }
Emeric Brun674b7432012-11-08 19:21:55 +01001225 goto out_error;
1226 }
1227 else {
1228 /* Fail on all other handshake errors */
1229 /* Note: OpenSSL may leave unread bytes in the socket's
1230 * buffer, causing an RST to be emitted upon close() on
1231 * TCP sockets. We first try to drain possibly pending
1232 * data to avoid this as much as possible.
1233 */
Willy Tarreauf79c8172013-10-21 16:30:56 +02001234 if ((conn->flags & CO_FL_CTRL_READY) && conn->ctrl && conn->ctrl->drain)
Willy Tarreau2b57cb82013-06-10 19:56:38 +02001235 conn->ctrl->drain(conn->t.sock.fd);
Willy Tarreau20879a02012-12-03 16:32:10 +01001236 if (!conn->err_code)
1237 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01001238 goto out_error;
1239 }
1240 }
1241 /* read some data: consider handshake completed */
1242 goto reneg_ok;
1243 }
1244
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001245 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001246 if (ret != 1) {
1247 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001248 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001249
1250 if (ret == SSL_ERROR_WANT_WRITE) {
1251 /* SSL handshake needs to write, L4 connection may not be ready */
1252 __conn_sock_stop_recv(conn);
1253 __conn_sock_poll_send(conn);
1254 return 0;
1255 }
1256 else if (ret == SSL_ERROR_WANT_READ) {
1257 /* SSL handshake needs to read, L4 connection is ready */
1258 if (conn->flags & CO_FL_WAIT_L4_CONN)
1259 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1260 __conn_sock_stop_send(conn);
1261 __conn_sock_poll_recv(conn);
1262 return 0;
1263 }
Willy Tarreau89230192012-09-28 20:22:13 +02001264 else if (ret == SSL_ERROR_SYSCALL) {
1265 /* if errno is null, then connection was successfully established */
1266 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1267 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001268
1269 if (!((SSL *)conn->xprt_ctx)->packet_length)
1270 if (!errno)
1271 conn->err_code = CO_ER_SSL_EMPTY;
1272 else
1273 conn->err_code = CO_ER_SSL_ABORT;
1274 else
1275 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +02001276 goto out_error;
1277 }
Emeric Brun46591952012-05-18 15:47:34 +02001278 else {
1279 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02001280 /* Note: OpenSSL may leave unread bytes in the socket's
1281 * buffer, causing an RST to be emitted upon close() on
1282 * TCP sockets. We first try to drain possibly pending
1283 * data to avoid this as much as possible.
1284 */
Willy Tarreauf79c8172013-10-21 16:30:56 +02001285 if ((conn->flags & CO_FL_CTRL_READY) && conn->ctrl && conn->ctrl->drain)
Willy Tarreau2b57cb82013-06-10 19:56:38 +02001286 conn->ctrl->drain(conn->t.sock.fd);
Willy Tarreau20879a02012-12-03 16:32:10 +01001287 if (!conn->err_code)
1288 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001289 goto out_error;
1290 }
1291 }
1292
Emeric Brun674b7432012-11-08 19:21:55 +01001293reneg_ok:
1294
Emeric Brun46591952012-05-18 15:47:34 +02001295 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001296 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001297 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +02001298 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001299 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1300 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001301
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001302 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001303 }
1304 }
1305
1306 /* The connection is now established at both layers, it's time to leave */
1307 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1308 return 1;
1309
1310 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001311 /* Clear openssl global errors stack */
1312 ERR_clear_error();
1313
Emeric Brun9fa89732012-10-04 17:09:56 +02001314 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001315 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1316 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1317 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001318 }
1319
Emeric Brun46591952012-05-18 15:47:34 +02001320 /* Fail on all other handshake errors */
1321 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001322 if (!conn->err_code)
1323 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001324 return 0;
1325}
1326
1327/* Receive up to <count> bytes from connection <conn>'s socket and store them
1328 * into buffer <buf>. The caller must ensure that <count> is always smaller
1329 * than the buffer's size. Only one call to recv() is performed, unless the
1330 * buffer wraps, in which case a second call may be performed. The connection's
1331 * flags are updated with whatever special event is detected (error, read0,
1332 * empty). The caller is responsible for taking care of those events and
1333 * avoiding the call if inappropriate. The function does not call the
1334 * connection's polling update function, so the caller is responsible for this.
1335 */
1336static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1337{
1338 int ret, done = 0;
1339 int try = count;
1340
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001341 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001342 goto out_error;
1343
1344 if (conn->flags & CO_FL_HANDSHAKE)
1345 /* a handshake was requested */
1346 return 0;
1347
1348 /* compute the maximum block size we can read at once. */
1349 if (buffer_empty(buf)) {
1350 /* let's realign the buffer to optimize I/O */
1351 buf->p = buf->data;
1352 }
1353 else if (buf->data + buf->o < buf->p &&
1354 buf->p + buf->i < buf->data + buf->size) {
1355 /* remaining space wraps at the end, with a moving limit */
1356 if (try > buf->data + buf->size - (buf->p + buf->i))
1357 try = buf->data + buf->size - (buf->p + buf->i);
1358 }
1359
1360 /* read the largest possible block. For this, we perform only one call
1361 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1362 * in which case we accept to do it once again. A new attempt is made on
1363 * EINTR too.
1364 */
1365 while (try) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001366 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001367 if (conn->flags & CO_FL_ERROR) {
1368 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001369 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001370 }
Emeric Brun46591952012-05-18 15:47:34 +02001371 if (ret > 0) {
1372 buf->i += ret;
1373 done += ret;
1374 if (ret < try)
1375 break;
1376 count -= ret;
1377 try = count;
1378 }
1379 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001380 ret = SSL_get_error(conn->xprt_ctx, ret);
1381 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001382 /* error on protocol or underlying transport */
1383 if ((ret != SSL_ERROR_SYSCALL)
1384 || (errno && (errno != EAGAIN)))
1385 conn->flags |= CO_FL_ERROR;
1386
Emeric Brun644cde02012-12-14 11:21:13 +01001387 /* Clear openssl global errors stack */
1388 ERR_clear_error();
1389 }
Emeric Brun46591952012-05-18 15:47:34 +02001390 goto read0;
1391 }
1392 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001393 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001394 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001395 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001396 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001397 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001398 break;
1399 }
1400 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001401 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1402 /* handshake is running, and it may need to re-enable read */
1403 conn->flags |= CO_FL_SSL_WAIT_HS;
1404 __conn_sock_want_recv(conn);
1405 break;
1406 }
Emeric Brun46591952012-05-18 15:47:34 +02001407 /* we need to poll for retry a read later */
1408 __conn_data_poll_recv(conn);
1409 break;
1410 }
1411 /* otherwise it's a real error */
1412 goto out_error;
1413 }
1414 }
1415 return done;
1416
1417 read0:
1418 conn_sock_read0(conn);
1419 return done;
1420 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001421 /* Clear openssl global errors stack */
1422 ERR_clear_error();
1423
Emeric Brun46591952012-05-18 15:47:34 +02001424 conn->flags |= CO_FL_ERROR;
1425 return done;
1426}
1427
1428
1429/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1430 * <flags> may contain MSG_MORE to make the system hold on without sending
1431 * data too fast, but this flag is ignored at the moment.
1432 * Only one call to send() is performed, unless the buffer wraps, in which case
1433 * a second call may be performed. The connection's flags are updated with
1434 * whatever special event is detected (error, empty). The caller is responsible
1435 * for taking care of those events and avoiding the call if inappropriate. The
1436 * function does not call the connection's polling update function, so the caller
1437 * is responsible for this.
1438 */
1439static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1440{
1441 int ret, try, done;
1442
1443 done = 0;
1444
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001445 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001446 goto out_error;
1447
1448 if (conn->flags & CO_FL_HANDSHAKE)
1449 /* a handshake was requested */
1450 return 0;
1451
1452 /* send the largest possible block. For this we perform only one call
1453 * to send() unless the buffer wraps and we exactly fill the first hunk,
1454 * in which case we accept to do it once again.
1455 */
1456 while (buf->o) {
Kevin Hestercad82342013-05-30 15:12:41 -07001457 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01001458
1459 if (global.tune.ssl_max_record && try > global.tune.ssl_max_record)
1460 try = global.tune.ssl_max_record;
1461
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001462 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001463 if (conn->flags & CO_FL_ERROR) {
1464 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001465 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001466 }
Emeric Brun46591952012-05-18 15:47:34 +02001467 if (ret > 0) {
1468 buf->o -= ret;
1469 done += ret;
1470
Willy Tarreau5fb38032012-12-16 19:39:09 +01001471 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001472 /* optimize data alignment in the buffer */
1473 buf->p = buf->data;
1474
1475 /* if the system buffer is full, don't insist */
1476 if (ret < try)
1477 break;
1478 }
1479 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001480 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001481 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001482 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1483 /* handshake is running, and it may need to re-enable write */
1484 conn->flags |= CO_FL_SSL_WAIT_HS;
1485 __conn_sock_want_send(conn);
1486 break;
1487 }
Emeric Brun46591952012-05-18 15:47:34 +02001488 /* we need to poll to retry a write later */
1489 __conn_data_poll_send(conn);
1490 break;
1491 }
1492 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001493 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001494 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001495 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001496 break;
1497 }
1498 goto out_error;
1499 }
1500 }
1501 return done;
1502
1503 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001504 /* Clear openssl global errors stack */
1505 ERR_clear_error();
1506
Emeric Brun46591952012-05-18 15:47:34 +02001507 conn->flags |= CO_FL_ERROR;
1508 return done;
1509}
1510
Emeric Brun46591952012-05-18 15:47:34 +02001511static void ssl_sock_close(struct connection *conn) {
1512
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001513 if (conn->xprt_ctx) {
1514 SSL_free(conn->xprt_ctx);
1515 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001516 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001517 }
Emeric Brun46591952012-05-18 15:47:34 +02001518}
1519
1520/* This function tries to perform a clean shutdown on an SSL connection, and in
1521 * any case, flags the connection as reusable if no handshake was in progress.
1522 */
1523static void ssl_sock_shutw(struct connection *conn, int clean)
1524{
1525 if (conn->flags & CO_FL_HANDSHAKE)
1526 return;
1527 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001528 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1529 /* Clear openssl global errors stack */
1530 ERR_clear_error();
1531 }
Emeric Brun46591952012-05-18 15:47:34 +02001532
1533 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001534 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001535}
1536
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001537/* used for logging, may be changed for a sample fetch later */
1538const char *ssl_sock_get_cipher_name(struct connection *conn)
1539{
1540 if (!conn->xprt && !conn->xprt_ctx)
1541 return NULL;
1542 return SSL_get_cipher_name(conn->xprt_ctx);
1543}
1544
1545/* used for logging, may be changed for a sample fetch later */
1546const char *ssl_sock_get_proto_version(struct connection *conn)
1547{
1548 if (!conn->xprt && !conn->xprt_ctx)
1549 return NULL;
1550 return SSL_get_version(conn->xprt_ctx);
1551}
1552
Willy Tarreau8d598402012-10-22 17:58:39 +02001553/* Extract a serial from a cert, and copy it to a chunk.
1554 * Returns 1 if serial is found and copied, 0 if no serial found and
1555 * -1 if output is not large enough.
1556 */
1557static int
1558ssl_sock_get_serial(X509 *crt, struct chunk *out)
1559{
1560 ASN1_INTEGER *serial;
1561
1562 serial = X509_get_serialNumber(crt);
1563 if (!serial)
1564 return 0;
1565
1566 if (out->size < serial->length)
1567 return -1;
1568
1569 memcpy(out->str, serial->data, serial->length);
1570 out->len = serial->length;
1571 return 1;
1572}
1573
Emeric Brunce5ad802012-10-22 14:11:22 +02001574
1575/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1576 * Returns 1 if serial is found and copied, 0 if no valid time found
1577 * and -1 if output is not large enough.
1578 */
1579static int
1580ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1581{
1582 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1583 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1584
1585 if (gentm->length < 12)
1586 return 0;
1587 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1588 return 0;
1589 if (out->size < gentm->length-2)
1590 return -1;
1591
1592 memcpy(out->str, gentm->data+2, gentm->length-2);
1593 out->len = gentm->length-2;
1594 return 1;
1595 }
1596 else if (tm->type == V_ASN1_UTCTIME) {
1597 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1598
1599 if (utctm->length < 10)
1600 return 0;
1601 if (utctm->data[0] >= 0x35)
1602 return 0;
1603 if (out->size < utctm->length)
1604 return -1;
1605
1606 memcpy(out->str, utctm->data, utctm->length);
1607 out->len = utctm->length;
1608 return 1;
1609 }
1610
1611 return 0;
1612}
1613
Emeric Brun87855892012-10-17 17:39:35 +02001614/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1615 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1616 */
1617static int
1618ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1619{
1620 X509_NAME_ENTRY *ne;
1621 int i, j, n;
1622 int cur = 0;
1623 const char *s;
1624 char tmp[128];
1625
1626 out->len = 0;
1627 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1628 if (pos < 0)
1629 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1630 else
1631 j = i;
1632
1633 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1634 n = OBJ_obj2nid(ne->object);
1635 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1636 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1637 s = tmp;
1638 }
1639
1640 if (chunk_strcasecmp(entry, s) != 0)
1641 continue;
1642
1643 if (pos < 0)
1644 cur--;
1645 else
1646 cur++;
1647
1648 if (cur != pos)
1649 continue;
1650
1651 if (ne->value->length > out->size)
1652 return -1;
1653
1654 memcpy(out->str, ne->value->data, ne->value->length);
1655 out->len = ne->value->length;
1656 return 1;
1657 }
1658
1659 return 0;
1660
1661}
1662
1663/* Extract and format full DN from a X509_NAME and copy result into a chunk
1664 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1665 */
1666static int
1667ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1668{
1669 X509_NAME_ENTRY *ne;
1670 int i, n, ln;
1671 int l = 0;
1672 const char *s;
1673 char *p;
1674 char tmp[128];
1675
1676 out->len = 0;
1677 p = out->str;
1678 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1679 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1680 n = OBJ_obj2nid(ne->object);
1681 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1682 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1683 s = tmp;
1684 }
1685 ln = strlen(s);
1686
1687 l += 1 + ln + 1 + ne->value->length;
1688 if (l > out->size)
1689 return -1;
1690 out->len = l;
1691
1692 *(p++)='/';
1693 memcpy(p, s, ln);
1694 p += ln;
1695 *(p++)='=';
1696 memcpy(p, ne->value->data, ne->value->length);
1697 p += ne->value->length;
1698 }
1699
1700 if (!out->len)
1701 return 0;
1702
1703 return 1;
1704}
1705
Willy Tarreau7875d092012-09-10 08:20:03 +02001706/***** Below are some sample fetching functions for ACL/patterns *****/
1707
Emeric Brune64aef12012-09-21 13:15:06 +02001708/* boolean, returns true if client cert was present */
1709static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001710smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001711 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brune64aef12012-09-21 13:15:06 +02001712{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001713 struct connection *conn;
1714
1715 if (!l4)
1716 return 0;
1717
1718 conn = objt_conn(l4->si[0].end);
1719 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001720 return 0;
1721
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001722 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001723 smp->flags |= SMP_F_MAY_CHANGE;
1724 return 0;
1725 }
1726
1727 smp->flags = 0;
1728 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001729 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001730
1731 return 1;
1732}
1733
Willy Tarreau8d598402012-10-22 17:58:39 +02001734/* bin, returns serial in a binary chunk */
1735static int
1736smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001737 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02001738{
1739 X509 *crt = NULL;
1740 int ret = 0;
1741 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001742 struct connection *conn;
1743
1744 if (!l4)
1745 return 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02001746
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001747 conn = objt_conn(l4->si[0].end);
1748 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001749 return 0;
1750
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001751 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001752 smp->flags |= SMP_F_MAY_CHANGE;
1753 return 0;
1754 }
1755
1756 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001757 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001758 if (!crt)
1759 goto out;
1760
Willy Tarreau47ca5452012-12-23 20:22:19 +01001761 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001762 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1763 goto out;
1764
1765 smp->data.str = *smp_trash;
1766 smp->type = SMP_T_BIN;
1767 ret = 1;
1768out:
1769 if (crt)
1770 X509_free(crt);
1771 return ret;
1772}
Emeric Brune64aef12012-09-21 13:15:06 +02001773
James Votha051b4a2013-05-14 20:37:59 +02001774/* bin, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk */
1775static int
1776smp_fetch_ssl_c_sha1(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001777 const struct arg *args, struct sample *smp, const char *kw)
James Votha051b4a2013-05-14 20:37:59 +02001778{
1779 X509 *crt = NULL;
1780 const EVP_MD *digest;
1781 int ret = 0;
1782 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001783 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02001784
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001785 if (!l4)
James Votha051b4a2013-05-14 20:37:59 +02001786 return 0;
1787
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001788 conn = objt_conn(l4->si[0].end);
1789 if (!conn || conn->xprt != &ssl_sock)
1790 return 0;
1791
1792 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02001793 smp->flags |= SMP_F_MAY_CHANGE;
1794 return 0;
1795 }
1796
1797 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001798 crt = SSL_get_peer_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02001799 if (!crt)
1800 goto out;
1801
1802 smp_trash = get_trash_chunk();
1803 digest = EVP_sha1();
1804 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
1805
1806 smp->data.str = *smp_trash;
1807 smp->type = SMP_T_BIN;
1808 ret = 1;
1809out:
1810 if (crt)
1811 X509_free(crt);
1812 return ret;
1813}
1814
Emeric Brunce5ad802012-10-22 14:11:22 +02001815/*str, returns notafter date in ASN1_UTCTIME format */
1816static int
1817smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001818 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001819{
1820 X509 *crt = NULL;
1821 int ret = 0;
1822 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001823 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02001824
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001825 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02001826 return 0;
1827
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001828 conn = objt_conn(l4->si[0].end);
1829 if (!conn || conn->xprt != &ssl_sock)
1830 return 0;
1831
1832 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001833 smp->flags |= SMP_F_MAY_CHANGE;
1834 return 0;
1835 }
1836
1837 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001838 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001839 if (!crt)
1840 goto out;
1841
Willy Tarreau47ca5452012-12-23 20:22:19 +01001842 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001843 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1844 goto out;
1845
1846 smp->data.str = *smp_trash;
1847 smp->type = SMP_T_STR;
1848 ret = 1;
1849out:
1850 if (crt)
1851 X509_free(crt);
1852 return ret;
1853}
1854
Emeric Brun87855892012-10-17 17:39:35 +02001855/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1856static int
1857smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001858 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02001859{
1860 X509 *crt = NULL;
1861 X509_NAME *name;
1862 int ret = 0;
1863 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001864 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02001865
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001866 if (!l4)
Emeric Brun87855892012-10-17 17:39:35 +02001867 return 0;
1868
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001869 conn = objt_conn(l4->si[0].end);
1870 if (!conn || conn->xprt != &ssl_sock)
1871 return 0;
1872
1873 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001874 smp->flags |= SMP_F_MAY_CHANGE;
1875 return 0;
1876 }
1877
1878 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001879 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001880 if (!crt)
1881 goto out;
1882
1883 name = X509_get_issuer_name(crt);
1884 if (!name)
1885 goto out;
1886
Willy Tarreau47ca5452012-12-23 20:22:19 +01001887 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001888 if (args && args[0].type == ARGT_STR) {
1889 int pos = 1;
1890
1891 if (args[1].type == ARGT_SINT)
1892 pos = args[1].data.sint;
1893 else if (args[1].type == ARGT_UINT)
1894 pos =(int)args[1].data.uint;
1895
1896 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1897 goto out;
1898 }
1899 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1900 goto out;
1901
1902 smp->type = SMP_T_STR;
1903 smp->data.str = *smp_trash;
1904 ret = 1;
1905out:
1906 if (crt)
1907 X509_free(crt);
1908 return ret;
1909}
1910
Emeric Brunce5ad802012-10-22 14:11:22 +02001911/*str, returns notbefore date in ASN1_UTCTIME format */
1912static int
1913smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001914 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001915{
1916 X509 *crt = NULL;
1917 int ret = 0;
1918 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001919 struct connection *conn;
1920
1921 if (!l4)
1922 return 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02001923
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001924 conn = objt_conn(l4->si[0].end);
1925 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001926 return 0;
1927
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001928 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001929 smp->flags |= SMP_F_MAY_CHANGE;
1930 return 0;
1931 }
1932
1933 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001934 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001935 if (!crt)
1936 goto out;
1937
Willy Tarreau47ca5452012-12-23 20:22:19 +01001938 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001939 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1940 goto out;
1941
1942 smp->data.str = *smp_trash;
1943 smp->type = SMP_T_STR;
1944 ret = 1;
1945out:
1946 if (crt)
1947 X509_free(crt);
1948 return ret;
1949}
1950
Emeric Brun87855892012-10-17 17:39:35 +02001951/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1952static int
1953smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001954 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02001955{
1956 X509 *crt = NULL;
1957 X509_NAME *name;
1958 int ret = 0;
1959 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001960 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02001961
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001962 if (!l4)
Emeric Brun87855892012-10-17 17:39:35 +02001963 return 0;
1964
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001965 conn = objt_conn(l4->si[0].end);
1966 if (!conn || conn->xprt != &ssl_sock)
1967 return 0;
1968
1969 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001970 smp->flags |= SMP_F_MAY_CHANGE;
1971 return 0;
1972 }
1973
1974 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001975 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001976 if (!crt)
1977 goto out;
1978
1979 name = X509_get_subject_name(crt);
1980 if (!name)
1981 goto out;
1982
Willy Tarreau47ca5452012-12-23 20:22:19 +01001983 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001984 if (args && args[0].type == ARGT_STR) {
1985 int pos = 1;
1986
1987 if (args[1].type == ARGT_SINT)
1988 pos = args[1].data.sint;
1989 else if (args[1].type == ARGT_UINT)
1990 pos =(int)args[1].data.uint;
1991
1992 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1993 goto out;
1994 }
1995 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1996 goto out;
1997
1998 smp->type = SMP_T_STR;
1999 smp->data.str = *smp_trash;
2000 ret = 1;
2001out:
2002 if (crt)
2003 X509_free(crt);
2004 return ret;
2005}
Emeric Brun9143d372012-12-20 15:44:16 +01002006
2007/* integer, returns true if current session use a client certificate */
2008static int
2009smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002010 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun9143d372012-12-20 15:44:16 +01002011{
2012 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002013 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01002014
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002015 if (!l4)
Emeric Brun9143d372012-12-20 15:44:16 +01002016 return 0;
2017
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002018 conn = objt_conn(l4->si[0].end);
2019 if (!conn || conn->xprt != &ssl_sock)
2020 return 0;
2021
2022 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01002023 smp->flags |= SMP_F_MAY_CHANGE;
2024 return 0;
2025 }
2026
2027 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002028 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01002029 if (crt) {
2030 X509_free(crt);
2031 }
2032
2033 smp->type = SMP_T_BOOL;
2034 smp->data.uint = (crt != NULL);
2035 return 1;
2036}
2037
Emeric Bruna7359fd2012-10-17 15:03:11 +02002038/* integer, returns the client certificate version */
2039static int
2040smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002041 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002042{
2043 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002044 struct connection *conn;
2045
2046 if (!l4)
2047 return 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02002048
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002049 conn = objt_conn(l4->si[0].end);
2050 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002051 return 0;
2052
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002053 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002054 smp->flags |= SMP_F_MAY_CHANGE;
2055 return 0;
2056 }
2057
2058 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002059 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002060 if (!crt)
2061 return 0;
2062
2063 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2064 X509_free(crt);
2065 smp->type = SMP_T_UINT;
2066
2067 return 1;
2068}
2069
Emeric Brun7f56e742012-10-19 18:15:40 +02002070/* str, returns the client certificate sig alg */
2071static int
2072smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002073 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002074{
2075 X509 *crt;
2076 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002077 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02002078
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002079 if (!l4)
Emeric Brun7f56e742012-10-19 18:15:40 +02002080 return 0;
2081
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002082 conn = objt_conn(l4->si[0].end);
2083 if (!conn || conn->xprt != &ssl_sock)
2084 return 0;
2085
2086 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002087 smp->flags |= SMP_F_MAY_CHANGE;
2088 return 0;
2089 }
2090
2091 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002092 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002093 if (!crt)
2094 return 0;
2095
2096 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2097
2098 smp->data.str.str = (char *)OBJ_nid2sn(nid);
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002099 if (!smp->data.str.str) {
2100 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02002101 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002102 }
Emeric Brun7f56e742012-10-19 18:15:40 +02002103
2104 smp->type = SMP_T_CSTR;
2105 smp->data.str.len = strlen(smp->data.str.str);
2106 X509_free(crt);
2107
2108 return 1;
2109}
2110
Emeric Brun521a0112012-10-22 12:22:55 +02002111/* str, returns the client certificate key alg */
2112static int
2113smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002114 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002115{
2116 X509 *crt;
2117 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002118 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02002119
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002120 if (!l4)
Emeric Brun521a0112012-10-22 12:22:55 +02002121 return 0;
2122
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002123 conn = objt_conn(l4->si[0].end);
2124 if (!conn || conn->xprt != &ssl_sock)
2125 return 0;
2126
2127 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002128 smp->flags |= SMP_F_MAY_CHANGE;
2129 return 0;
2130 }
2131
2132 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002133 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002134 if (!crt)
2135 return 0;
2136
2137 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2138
2139 smp->data.str.str = (char *)OBJ_nid2sn(nid);
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002140 if (!smp->data.str.str) {
2141 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02002142 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002143 }
Emeric Brun521a0112012-10-22 12:22:55 +02002144
2145 smp->type = SMP_T_CSTR;
2146 smp->data.str.len = strlen(smp->data.str.str);
2147 X509_free(crt);
2148
2149 return 1;
2150}
2151
Emeric Brun2525b6b2012-10-18 15:59:43 +02002152/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02002153static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002154smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002155 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002156{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002157 struct connection *conn = objt_conn(l4->si[0].end);
2158
Willy Tarreau7875d092012-09-10 08:20:03 +02002159 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002160 smp->data.uint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02002161 return 1;
2162}
2163
Emeric Brun2525b6b2012-10-18 15:59:43 +02002164/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02002165static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002166smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002167 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002168{
2169#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002170 struct connection *conn = objt_conn(l4->si[0].end);
2171
Willy Tarreau7875d092012-09-10 08:20:03 +02002172 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002173 smp->data.uint = (conn && conn->xprt == &ssl_sock) &&
2174 conn->xprt_ctx &&
2175 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02002176 return 1;
2177#else
2178 return 0;
2179#endif
2180}
2181
Willy Tarreau8d598402012-10-22 17:58:39 +02002182/* bin, returns serial in a binary chunk */
2183static int
2184smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002185 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02002186{
2187 X509 *crt = NULL;
2188 int ret = 0;
2189 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002190 struct connection *conn;
2191
2192 if (!l4)
2193 return 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02002194
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002195 conn = objt_conn(l4->si[0].end);
2196 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02002197 return 0;
2198
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002199 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02002200 smp->flags |= SMP_F_MAY_CHANGE;
2201 return 0;
2202 }
2203
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002204 crt = SSL_get_certificate(conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02002205 if (!crt)
2206 goto out;
2207
Willy Tarreau47ca5452012-12-23 20:22:19 +01002208 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02002209 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
2210 goto out;
2211
2212 smp->data.str = *smp_trash;
2213 smp->type = SMP_T_BIN;
2214 ret = 1;
2215out:
2216 return ret;
2217}
Emeric Brunce5ad802012-10-22 14:11:22 +02002218/*str, returns notafter date in ASN1_UTCTIME format */
2219static int
2220smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002221 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002222{
2223 X509 *crt = NULL;
2224 int ret = 0;
2225 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002226 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02002227
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002228 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02002229 return 0;
2230
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002231 conn = objt_conn(l4->si[0].end);
2232 if (!conn || conn->xprt != &ssl_sock)
2233 return 0;
2234
2235 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002236 smp->flags |= SMP_F_MAY_CHANGE;
2237 return 0;
2238 }
2239
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002240 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002241 if (!crt)
2242 goto out;
2243
Willy Tarreau47ca5452012-12-23 20:22:19 +01002244 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002245 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
2246 goto out;
2247
2248 smp->data.str = *smp_trash;
2249 smp->type = SMP_T_STR;
2250 ret = 1;
2251out:
2252 return ret;
2253}
2254
2255/*str, returns notbefore date in ASN1_UTCTIME format */
2256static int
2257smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002258 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002259{
2260 X509 *crt = NULL;
2261 int ret = 0;
2262 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002263 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02002264
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002265 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02002266 return 0;
2267
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002268 conn = objt_conn(l4->si[0].end);
2269 if (!conn || conn->xprt != &ssl_sock)
2270 return 0;
2271
2272 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002273 smp->flags |= SMP_F_MAY_CHANGE;
2274 return 0;
2275 }
2276
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002277 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002278 if (!crt)
2279 goto out;
2280
Willy Tarreau47ca5452012-12-23 20:22:19 +01002281 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002282 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
2283 goto out;
2284
2285 smp->data.str = *smp_trash;
2286 smp->type = SMP_T_STR;
2287 ret = 1;
2288out:
2289 return ret;
2290}
Willy Tarreau8d598402012-10-22 17:58:39 +02002291
Emeric Bruna7359fd2012-10-17 15:03:11 +02002292/* integer, returns the frontend certificate version */
2293static int
2294smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002295 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002296{
2297 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002298 struct connection *conn;
Emeric Bruna7359fd2012-10-17 15:03:11 +02002299
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002300 if (!l4)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002301 return 0;
2302
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002303 conn = objt_conn(l4->si[0].end);
2304 if (!conn || conn->xprt != &ssl_sock)
2305 return 0;
2306
2307 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002308 smp->flags |= SMP_F_MAY_CHANGE;
2309 return 0;
2310 }
2311
2312 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002313 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002314 if (!crt)
2315 return 0;
2316
2317 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2318 smp->type = SMP_T_UINT;
2319
2320 return 1;
2321}
2322
Emeric Brun7f56e742012-10-19 18:15:40 +02002323/* str, returns the client certificate sig alg */
2324static int
2325smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002326 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002327{
2328 X509 *crt;
2329 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002330 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02002331
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002332 if (!l4)
Emeric Brun7f56e742012-10-19 18:15:40 +02002333 return 0;
2334
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002335 conn = objt_conn(l4->si[0].end);
2336 if (!conn || conn->xprt != &ssl_sock)
2337 return 0;
2338
2339 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002340 smp->flags |= SMP_F_MAY_CHANGE;
2341 return 0;
2342 }
2343
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002344 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002345 if (!crt)
2346 return 0;
2347
2348 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2349
2350 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2351 if (!smp->data.str.str)
2352 return 0;
2353
2354 smp->type = SMP_T_CSTR;
2355 smp->data.str.len = strlen(smp->data.str.str);
2356
2357 return 1;
2358}
2359
Emeric Brun521a0112012-10-22 12:22:55 +02002360/* str, returns the client certificate key alg */
2361static int
2362smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002363 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002364{
2365 X509 *crt;
2366 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002367 struct connection *conn;
2368
2369 if (!l4)
2370 return 0;
Emeric Brun521a0112012-10-22 12:22:55 +02002371
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002372 conn = objt_conn(l4->si[0].end);
2373 if (!conn || conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002374 return 0;
2375
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002376 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002377 smp->flags |= SMP_F_MAY_CHANGE;
2378 return 0;
2379 }
2380
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002381 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002382 if (!crt)
2383 return 0;
2384
2385 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2386
2387 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2388 if (!smp->data.str.str)
2389 return 0;
2390
2391 smp->type = SMP_T_CSTR;
2392 smp->data.str.len = strlen(smp->data.str.str);
2393
2394 return 1;
2395}
2396
Emeric Brun87855892012-10-17 17:39:35 +02002397/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2398static int
2399smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002400 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002401{
2402 X509 *crt = NULL;
2403 X509_NAME *name;
2404 int ret = 0;
2405 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002406 struct connection *conn;
2407
2408 if (!l4)
2409 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02002410
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002411 conn = objt_conn(l4->si[0].end);
2412 if (!conn || conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002413 return 0;
2414
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002415 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002416 smp->flags |= SMP_F_MAY_CHANGE;
2417 return 0;
2418 }
2419
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002420 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002421 if (!crt)
2422 goto out;
2423
2424 name = X509_get_issuer_name(crt);
2425 if (!name)
2426 goto out;
2427
Willy Tarreau47ca5452012-12-23 20:22:19 +01002428 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002429 if (args && args[0].type == ARGT_STR) {
2430 int pos = 1;
2431
2432 if (args[1].type == ARGT_SINT)
2433 pos = args[1].data.sint;
2434 else if (args[1].type == ARGT_UINT)
2435 pos =(int)args[1].data.uint;
2436
2437 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2438 goto out;
2439 }
2440 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2441 goto out;
2442
2443 smp->type = SMP_T_STR;
2444 smp->data.str = *smp_trash;
2445 ret = 1;
2446out:
2447 return ret;
2448}
2449
2450/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2451static int
2452smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002453 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002454{
2455 X509 *crt = NULL;
2456 X509_NAME *name;
2457 int ret = 0;
2458 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002459 struct connection *conn;
2460
2461 if (!l4)
2462 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02002463
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002464 conn = objt_conn(l4->si[0].end);
2465 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002466 return 0;
2467
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002468 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002469 smp->flags |= SMP_F_MAY_CHANGE;
2470 return 0;
2471 }
2472
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002473 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002474 if (!crt)
2475 goto out;
2476
2477 name = X509_get_subject_name(crt);
2478 if (!name)
2479 goto out;
2480
Willy Tarreau47ca5452012-12-23 20:22:19 +01002481 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002482 if (args && args[0].type == ARGT_STR) {
2483 int pos = 1;
2484
2485 if (args[1].type == ARGT_SINT)
2486 pos = args[1].data.sint;
2487 else if (args[1].type == ARGT_UINT)
2488 pos =(int)args[1].data.uint;
2489
2490 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2491 goto out;
2492 }
2493 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2494 goto out;
2495
2496 smp->type = SMP_T_STR;
2497 smp->data.str = *smp_trash;
2498 ret = 1;
2499out:
2500 return ret;
2501}
2502
Emeric Brun589fcad2012-10-16 14:13:26 +02002503static int
2504smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002505 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002506{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002507 struct connection *conn;
2508
Emeric Brun589fcad2012-10-16 14:13:26 +02002509 smp->flags = 0;
2510
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002511 if (!l4)
2512 return 0;
2513
2514 conn = objt_conn(l4->si[0].end);
2515 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002516 return 0;
2517
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002518 smp->data.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002519 if (!smp->data.str.str)
2520 return 0;
2521
2522 smp->type = SMP_T_CSTR;
2523 smp->data.str.len = strlen(smp->data.str.str);
2524
2525 return 1;
2526}
2527
2528static int
2529smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002530 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002531{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002532 struct connection *conn;
2533
Emeric Brun589fcad2012-10-16 14:13:26 +02002534 smp->flags = 0;
2535
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002536 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002537 return 0;
2538
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002539 conn = objt_conn(l4->si[0].end);
2540 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002541 return 0;
2542
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002543 if (!SSL_get_cipher_bits(conn->xprt_ctx, (int *)&smp->data.uint))
2544 return 0;
2545
Emeric Brun589fcad2012-10-16 14:13:26 +02002546 smp->type = SMP_T_UINT;
2547
2548 return 1;
2549}
2550
2551static int
2552smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002553 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002554{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002555 struct connection *conn;
2556
Emeric Brun589fcad2012-10-16 14:13:26 +02002557 smp->flags = 0;
2558
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002559 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002560 return 0;
2561
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002562 conn = objt_conn(l4->si[0].end);
2563 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2564 return 0;
2565
2566 smp->data.uint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002567 if (!smp->data.uint)
2568 return 0;
2569
2570 smp->type = SMP_T_UINT;
2571
2572 return 1;
2573}
2574
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002575#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002576static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002577smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002578 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002579{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002580 struct connection *conn;
2581
Willy Tarreaua33c6542012-10-15 13:19:06 +02002582 smp->flags = 0;
2583 smp->type = SMP_T_CSTR;
2584
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002585 if (!l4)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002586 return 0;
2587
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002588 conn = objt_conn(l4->si[0].end);
2589 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2590 return 0;
2591
Willy Tarreaua33c6542012-10-15 13:19:06 +02002592 smp->data.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002593 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002594 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2595
2596 if (!smp->data.str.str)
2597 return 0;
2598
2599 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002600}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002601#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002602
Willy Tarreauab861d32013-04-02 02:30:41 +02002603#ifdef OPENSSL_ALPN_NEGOTIATED
2604static int
2605smp_fetch_ssl_fc_alpn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002606 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreauab861d32013-04-02 02:30:41 +02002607{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002608 struct connection *conn;
2609
Willy Tarreauab861d32013-04-02 02:30:41 +02002610 smp->flags = 0;
2611 smp->type = SMP_T_CSTR;
2612
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002613 if (!l4)
2614 return 0;
2615
2616 conn = objt_conn(l4->si[0].end);
2617 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02002618 return 0;
2619
2620 smp->data.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002621 SSL_get0_alpn_negotiated(conn->xprt_ctx,
Willy Tarreauab861d32013-04-02 02:30:41 +02002622 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2623
2624 if (!smp->data.str.str)
2625 return 0;
2626
2627 return 1;
2628}
2629#endif
2630
Willy Tarreaua33c6542012-10-15 13:19:06 +02002631static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002632smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002633 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002634{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002635 struct connection *conn;
2636
Emeric Brun589fcad2012-10-16 14:13:26 +02002637 smp->flags = 0;
2638
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002639 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002640 return 0;
2641
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002642 conn = objt_conn(l4->si[0].end);
2643 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2644 return 0;
2645
2646 smp->data.str.str = (char *)SSL_get_version(conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002647 if (!smp->data.str.str)
2648 return 0;
2649
2650 smp->type = SMP_T_CSTR;
2651 smp->data.str.len = strlen(smp->data.str.str);
2652
2653 return 1;
2654}
2655
2656static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002657smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002658 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunfe68f682012-10-16 14:59:28 +02002659{
2660#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2661 SSL_SESSION *sess;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002662 struct connection *conn;
Emeric Brunfe68f682012-10-16 14:59:28 +02002663
2664 smp->flags = 0;
2665 smp->type = SMP_T_CBIN;
2666
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002667 if (!l4)
Emeric Brunfe68f682012-10-16 14:59:28 +02002668 return 0;
2669
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002670 conn = objt_conn(l4->si[0].end);
2671 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2672 return 0;
2673
2674 sess = SSL_get_session(conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002675 if (!sess)
2676 return 0;
2677
2678 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2679 if (!smp->data.str.str || !&smp->data.str.len)
2680 return 0;
2681
2682 return 1;
2683#else
2684 return 0;
2685#endif
2686}
2687
2688static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002689smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002690 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002691{
2692#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002693 struct connection *conn;
2694
Willy Tarreau7875d092012-09-10 08:20:03 +02002695 smp->flags = 0;
2696 smp->type = SMP_T_CSTR;
2697
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002698 if (!l4)
Willy Tarreau7875d092012-09-10 08:20:03 +02002699 return 0;
2700
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002701 conn = objt_conn(l4->si[0].end);
2702 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2703 return 0;
2704
2705 smp->data.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau3e394c92012-09-14 23:56:58 +02002706 if (!smp->data.str.str)
2707 return 0;
2708
Willy Tarreau7875d092012-09-10 08:20:03 +02002709 smp->data.str.len = strlen(smp->data.str.str);
2710 return 1;
2711#else
2712 return 0;
2713#endif
2714}
2715
Emeric Brun2525b6b2012-10-18 15:59:43 +02002716/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002717static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002718smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002719 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002720{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002721 struct connection *conn;
2722
2723 if (!l4)
Emeric Brunf282a812012-09-21 15:27:54 +02002724 return 0;
2725
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002726 conn = objt_conn(l4->si[0].end);
2727 if (!conn || conn->xprt != &ssl_sock)
2728 return 0;
2729
2730 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002731 smp->flags = SMP_F_MAY_CHANGE;
2732 return 0;
2733 }
2734
2735 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002736 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002737 smp->flags = 0;
2738
2739 return 1;
2740}
2741
Emeric Brun2525b6b2012-10-18 15:59:43 +02002742/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002743static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002744smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002745 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002746{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002747 struct connection *conn;
2748
2749 if (!l4)
2750 return 0;
2751
2752 conn = objt_conn(l4->si[0].end);
2753 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002754 return 0;
2755
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002756 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002757 smp->flags = SMP_F_MAY_CHANGE;
2758 return 0;
2759 }
2760
2761 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002762 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002763 smp->flags = 0;
2764
2765 return 1;
2766}
2767
Emeric Brun2525b6b2012-10-18 15:59:43 +02002768/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002769static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002770smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002771 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002772{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002773 struct connection *conn;
2774
2775 if (!l4)
Emeric Brunf282a812012-09-21 15:27:54 +02002776 return 0;
2777
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002778 conn = objt_conn(l4->si[0].end);
2779 if (!conn || conn->xprt != &ssl_sock)
2780 return 0;
2781
2782 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002783 smp->flags = SMP_F_MAY_CHANGE;
2784 return 0;
2785 }
2786
2787 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002788 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002789 smp->flags = 0;
2790
2791 return 1;
2792}
2793
Emeric Brun2525b6b2012-10-18 15:59:43 +02002794/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002795static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002796smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002797 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002798{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002799 struct connection *conn;
2800
2801 if (!l4)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002802 return 0;
2803
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002804 conn = objt_conn(l4->si[0].end);
2805 if (!conn || conn->xprt != &ssl_sock)
2806 return 0;
2807
2808 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002809 smp->flags = SMP_F_MAY_CHANGE;
2810 return 0;
2811 }
2812
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002813 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002814 return 0;
2815
2816 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002817 smp->data.uint = (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002818 smp->flags = 0;
2819
2820 return 1;
2821}
2822
Emeric Brunfb510ea2012-10-05 12:00:26 +02002823/* parse the "ca-file" bind keyword */
2824static 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 +02002825{
2826 if (!*args[cur_arg + 1]) {
2827 if (err)
2828 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2829 return ERR_ALERT | ERR_FATAL;
2830 }
2831
Emeric Brunef42d922012-10-11 16:11:36 +02002832 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2833 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2834 else
2835 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002836
Emeric Brund94b3fe2012-09-20 18:23:56 +02002837 return 0;
2838}
2839
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002840/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002841static 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 +02002842{
2843 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002844 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002845 return ERR_ALERT | ERR_FATAL;
2846 }
2847
Emeric Brun76d88952012-10-05 15:47:31 +02002848 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002849 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002850 return 0;
2851}
2852
2853/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002854static 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 +02002855{
Willy Tarreau38011032013-08-13 16:59:39 +02002856 char path[MAXPATHLEN];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002857 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002858 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002859 return ERR_ALERT | ERR_FATAL;
2860 }
2861
Emeric Brunc8e8d122012-10-02 18:42:10 +02002862 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
Willy Tarreau38011032013-08-13 16:59:39 +02002863 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02002864 memprintf(err, "'%s' : path too long", args[cur_arg]);
2865 return ERR_ALERT | ERR_FATAL;
2866 }
2867 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2868 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2869 return ERR_ALERT | ERR_FATAL;
2870
2871 return 0;
2872 }
2873
Willy Tarreau4348fad2012-09-20 16:48:07 +02002874 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002875 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002876
2877 return 0;
2878}
2879
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002880/* parse the "crt-list" bind keyword */
2881static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2882{
2883 if (!*args[cur_arg + 1]) {
2884 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
2885 return ERR_ALERT | ERR_FATAL;
2886 }
2887
Willy Tarreauad1731d2013-04-02 17:35:58 +02002888 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
2889 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002890 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02002891 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002892
2893 return 0;
2894}
2895
Emeric Brunfb510ea2012-10-05 12:00:26 +02002896/* parse the "crl-file" bind keyword */
2897static 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 +02002898{
Emeric Brun051cdab2012-10-02 19:25:50 +02002899#ifndef X509_V_FLAG_CRL_CHECK
2900 if (err)
2901 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2902 return ERR_ALERT | ERR_FATAL;
2903#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002904 if (!*args[cur_arg + 1]) {
2905 if (err)
2906 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2907 return ERR_ALERT | ERR_FATAL;
2908 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002909
Emeric Brunef42d922012-10-11 16:11:36 +02002910 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2911 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2912 else
2913 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002914
Emeric Brun2b58d042012-09-20 17:10:03 +02002915 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002916#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002917}
2918
2919/* parse the "ecdhe" bind keyword keywords */
2920static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2921{
2922#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2923 if (err)
2924 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2925 return ERR_ALERT | ERR_FATAL;
2926#elif defined(OPENSSL_NO_ECDH)
2927 if (err)
2928 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2929 return ERR_ALERT | ERR_FATAL;
2930#else
2931 if (!*args[cur_arg + 1]) {
2932 if (err)
2933 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2934 return ERR_ALERT | ERR_FATAL;
2935 }
2936
2937 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002938
2939 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002940#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002941}
2942
Emeric Brun81c00f02012-09-21 14:31:21 +02002943/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2944static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2945{
2946 int code;
2947 char *p = args[cur_arg + 1];
2948 unsigned long long *ignerr = &conf->crt_ignerr;
2949
2950 if (!*p) {
2951 if (err)
2952 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2953 return ERR_ALERT | ERR_FATAL;
2954 }
2955
2956 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2957 ignerr = &conf->ca_ignerr;
2958
2959 if (strcmp(p, "all") == 0) {
2960 *ignerr = ~0ULL;
2961 return 0;
2962 }
2963
2964 while (p) {
2965 code = atoi(p);
2966 if ((code <= 0) || (code > 63)) {
2967 if (err)
2968 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2969 args[cur_arg], code, args[cur_arg + 1]);
2970 return ERR_ALERT | ERR_FATAL;
2971 }
2972 *ignerr |= 1ULL << code;
2973 p = strchr(p, ',');
2974 if (p)
2975 p++;
2976 }
2977
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002978 return 0;
2979}
2980
2981/* parse the "force-sslv3" bind keyword */
2982static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2983{
2984 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2985 return 0;
2986}
2987
2988/* parse the "force-tlsv10" bind keyword */
2989static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2990{
2991 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002992 return 0;
2993}
2994
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002995/* parse the "force-tlsv11" bind keyword */
2996static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2997{
2998#if SSL_OP_NO_TLSv1_1
2999 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
3000 return 0;
3001#else
3002 if (err)
3003 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
3004 return ERR_ALERT | ERR_FATAL;
3005#endif
3006}
3007
3008/* parse the "force-tlsv12" bind keyword */
3009static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3010{
3011#if SSL_OP_NO_TLSv1_2
3012 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
3013 return 0;
3014#else
3015 if (err)
3016 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
3017 return ERR_ALERT | ERR_FATAL;
3018#endif
3019}
3020
3021
Emeric Brun2d0c4822012-10-02 13:45:20 +02003022/* parse the "no-tls-tickets" bind keyword */
3023static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3024{
Emeric Brun89675492012-10-05 13:48:26 +02003025 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02003026 return 0;
3027}
3028
Emeric Brun2d0c4822012-10-02 13:45:20 +02003029
Emeric Brun9b3009b2012-10-05 11:55:06 +02003030/* parse the "no-sslv3" bind keyword */
3031static 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 +02003032{
Emeric Brun89675492012-10-05 13:48:26 +02003033 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003034 return 0;
3035}
3036
Emeric Brun9b3009b2012-10-05 11:55:06 +02003037/* parse the "no-tlsv10" bind keyword */
3038static 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 +02003039{
Emeric Brun89675492012-10-05 13:48:26 +02003040 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02003041 return 0;
3042}
3043
Emeric Brun9b3009b2012-10-05 11:55:06 +02003044/* parse the "no-tlsv11" bind keyword */
3045static 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 +02003046{
Emeric Brun89675492012-10-05 13:48:26 +02003047 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02003048 return 0;
3049}
3050
Emeric Brun9b3009b2012-10-05 11:55:06 +02003051/* parse the "no-tlsv12" bind keyword */
3052static 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 +02003053{
Emeric Brun89675492012-10-05 13:48:26 +02003054 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003055 return 0;
3056}
3057
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003058/* parse the "npn" bind keyword */
3059static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3060{
3061#ifdef OPENSSL_NPN_NEGOTIATED
3062 char *p1, *p2;
3063
3064 if (!*args[cur_arg + 1]) {
3065 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
3066 return ERR_ALERT | ERR_FATAL;
3067 }
3068
3069 free(conf->npn_str);
3070
3071 /* the NPN string is built as a suite of (<len> <name>)* */
3072 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
3073 conf->npn_str = calloc(1, conf->npn_len);
3074 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
3075
3076 /* replace commas with the name length */
3077 p1 = conf->npn_str;
3078 p2 = p1 + 1;
3079 while (1) {
3080 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
3081 if (!p2)
3082 p2 = p1 + 1 + strlen(p1 + 1);
3083
3084 if (p2 - (p1 + 1) > 255) {
3085 *p2 = '\0';
3086 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
3087 return ERR_ALERT | ERR_FATAL;
3088 }
3089
3090 *p1 = p2 - (p1 + 1);
3091 p1 = p2;
3092
3093 if (!*p2)
3094 break;
3095
3096 *(p2++) = '\0';
3097 }
3098 return 0;
3099#else
3100 if (err)
3101 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
3102 return ERR_ALERT | ERR_FATAL;
3103#endif
3104}
3105
Willy Tarreauab861d32013-04-02 02:30:41 +02003106/* parse the "alpn" bind keyword */
3107static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3108{
3109#ifdef OPENSSL_ALPN_NEGOTIATED
3110 char *p1, *p2;
3111
3112 if (!*args[cur_arg + 1]) {
3113 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
3114 return ERR_ALERT | ERR_FATAL;
3115 }
3116
3117 free(conf->alpn_str);
3118
3119 /* the ALPN string is built as a suite of (<len> <name>)* */
3120 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
3121 conf->alpn_str = calloc(1, conf->alpn_len);
3122 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
3123
3124 /* replace commas with the name length */
3125 p1 = conf->alpn_str;
3126 p2 = p1 + 1;
3127 while (1) {
3128 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
3129 if (!p2)
3130 p2 = p1 + 1 + strlen(p1 + 1);
3131
3132 if (p2 - (p1 + 1) > 255) {
3133 *p2 = '\0';
3134 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
3135 return ERR_ALERT | ERR_FATAL;
3136 }
3137
3138 *p1 = p2 - (p1 + 1);
3139 p1 = p2;
3140
3141 if (!*p2)
3142 break;
3143
3144 *(p2++) = '\0';
3145 }
3146 return 0;
3147#else
3148 if (err)
3149 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
3150 return ERR_ALERT | ERR_FATAL;
3151#endif
3152}
3153
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003154/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003155static 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 +02003156{
Willy Tarreau81796be2012-09-22 19:11:47 +02003157 struct listener *l;
3158
Willy Tarreau4348fad2012-09-20 16:48:07 +02003159 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02003160
3161 if (global.listen_default_ciphers && !conf->ciphers)
3162 conf->ciphers = strdup(global.listen_default_ciphers);
3163
Willy Tarreau81796be2012-09-22 19:11:47 +02003164 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003165 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02003166
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003167 return 0;
3168}
3169
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003170/* parse the "strict-sni" bind keyword */
3171static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3172{
3173 conf->strict_sni = 1;
3174 return 0;
3175}
3176
Emeric Brund94b3fe2012-09-20 18:23:56 +02003177/* parse the "verify" bind keyword */
3178static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3179{
3180 if (!*args[cur_arg + 1]) {
3181 if (err)
3182 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
3183 return ERR_ALERT | ERR_FATAL;
3184 }
3185
3186 if (strcmp(args[cur_arg + 1], "none") == 0)
3187 conf->verify = SSL_VERIFY_NONE;
3188 else if (strcmp(args[cur_arg + 1], "optional") == 0)
3189 conf->verify = SSL_VERIFY_PEER;
3190 else if (strcmp(args[cur_arg + 1], "required") == 0)
3191 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
3192 else {
3193 if (err)
3194 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
3195 args[cur_arg], args[cur_arg + 1]);
3196 return ERR_ALERT | ERR_FATAL;
3197 }
3198
3199 return 0;
3200}
3201
Willy Tarreau92faadf2012-10-10 23:04:25 +02003202/************** "server" keywords ****************/
3203
Emeric Brunef42d922012-10-11 16:11:36 +02003204/* parse the "ca-file" server keyword */
3205static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3206{
3207 if (!*args[*cur_arg + 1]) {
3208 if (err)
3209 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
3210 return ERR_ALERT | ERR_FATAL;
3211 }
3212
3213 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3214 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3215 else
3216 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
3217
3218 return 0;
3219}
3220
Willy Tarreau92faadf2012-10-10 23:04:25 +02003221/* parse the "check-ssl" server keyword */
3222static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3223{
3224 newsrv->check.use_ssl = 1;
3225 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3226 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3227 return 0;
3228}
3229
3230/* parse the "ciphers" server keyword */
3231static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3232{
3233 if (!*args[*cur_arg + 1]) {
3234 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
3235 return ERR_ALERT | ERR_FATAL;
3236 }
3237
3238 free(newsrv->ssl_ctx.ciphers);
3239 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
3240 return 0;
3241}
3242
Emeric Brunef42d922012-10-11 16:11:36 +02003243/* parse the "crl-file" server keyword */
3244static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3245{
3246#ifndef X509_V_FLAG_CRL_CHECK
3247 if (err)
3248 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
3249 return ERR_ALERT | ERR_FATAL;
3250#else
3251 if (!*args[*cur_arg + 1]) {
3252 if (err)
3253 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
3254 return ERR_ALERT | ERR_FATAL;
3255 }
3256
3257 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3258 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3259 else
3260 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
3261
3262 return 0;
3263#endif
3264}
3265
Emeric Bruna7aa3092012-10-26 12:58:00 +02003266/* parse the "crt" server keyword */
3267static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3268{
3269 if (!*args[*cur_arg + 1]) {
3270 if (err)
3271 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
3272 return ERR_ALERT | ERR_FATAL;
3273 }
3274
3275 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
3276 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3277 else
3278 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
3279
3280 return 0;
3281}
Emeric Brunef42d922012-10-11 16:11:36 +02003282
Willy Tarreau92faadf2012-10-10 23:04:25 +02003283/* parse the "force-sslv3" server keyword */
3284static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3285{
3286 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
3287 return 0;
3288}
3289
3290/* parse the "force-tlsv10" server keyword */
3291static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3292{
3293 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
3294 return 0;
3295}
3296
3297/* parse the "force-tlsv11" server keyword */
3298static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3299{
3300#if SSL_OP_NO_TLSv1_1
3301 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
3302 return 0;
3303#else
3304 if (err)
3305 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
3306 return ERR_ALERT | ERR_FATAL;
3307#endif
3308}
3309
3310/* parse the "force-tlsv12" server keyword */
3311static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3312{
3313#if SSL_OP_NO_TLSv1_2
3314 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
3315 return 0;
3316#else
3317 if (err)
3318 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
3319 return ERR_ALERT | ERR_FATAL;
3320#endif
3321}
3322
3323/* parse the "no-sslv3" server keyword */
3324static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3325{
3326 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
3327 return 0;
3328}
3329
3330/* parse the "no-tlsv10" server keyword */
3331static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3332{
3333 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
3334 return 0;
3335}
3336
3337/* parse the "no-tlsv11" server keyword */
3338static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3339{
3340 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
3341 return 0;
3342}
3343
3344/* parse the "no-tlsv12" server keyword */
3345static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3346{
3347 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
3348 return 0;
3349}
3350
Emeric Brunf9c5c472012-10-11 15:28:34 +02003351/* parse the "no-tls-tickets" server keyword */
3352static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3353{
3354 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
3355 return 0;
3356}
3357
Willy Tarreau92faadf2012-10-10 23:04:25 +02003358/* parse the "ssl" server keyword */
3359static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3360{
3361 newsrv->use_ssl = 1;
3362 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3363 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3364 return 0;
3365}
3366
Emeric Brunef42d922012-10-11 16:11:36 +02003367/* parse the "verify" server keyword */
3368static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3369{
3370 if (!*args[*cur_arg + 1]) {
3371 if (err)
3372 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
3373 return ERR_ALERT | ERR_FATAL;
3374 }
3375
3376 if (strcmp(args[*cur_arg + 1], "none") == 0)
3377 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
3378 else if (strcmp(args[*cur_arg + 1], "required") == 0)
3379 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
3380 else {
3381 if (err)
3382 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
3383 args[*cur_arg], args[*cur_arg + 1]);
3384 return ERR_ALERT | ERR_FATAL;
3385 }
3386
Evan Broderbe554312013-06-27 00:05:25 -07003387 return 0;
3388}
3389
3390/* parse the "verifyhost" server keyword */
3391static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3392{
3393 if (!*args[*cur_arg + 1]) {
3394 if (err)
3395 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
3396 return ERR_ALERT | ERR_FATAL;
3397 }
3398
3399 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
3400
Emeric Brunef42d922012-10-11 16:11:36 +02003401 return 0;
3402}
3403
Willy Tarreau7875d092012-09-10 08:20:03 +02003404/* Note: must not be declared <const> as its list will be overwritten.
3405 * Please take care of keeping this list alphabetically sorted.
3406 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003407static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Willy Tarreau80aca902013-01-07 15:42:20 +01003408 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3409 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3410 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3411 { "ssl_c_i_dn", smp_fetch_ssl_c_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3412 { "ssl_c_key_alg", smp_fetch_ssl_c_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3413 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3414 { "ssl_c_notbefore", smp_fetch_ssl_c_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3415 { "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3416 { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3417 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
James Votha051b4a2013-05-14 20:37:59 +02003418 { "ssl_c_sha1", smp_fetch_ssl_c_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01003419 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3420 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3421 { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3422 { "ssl_f_i_dn", smp_fetch_ssl_f_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3423 { "ssl_f_key_alg", smp_fetch_ssl_f_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3424 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3425 { "ssl_f_notbefore", smp_fetch_ssl_f_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3426 { "ssl_f_sig_alg", smp_fetch_ssl_f_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3427 { "ssl_f_s_dn", smp_fetch_ssl_f_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3428 { "ssl_f_serial", smp_fetch_ssl_f_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3429 { "ssl_f_version", smp_fetch_ssl_f_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3430 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3431 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3432 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3433 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3434 { "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 +02003435#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau80aca902013-01-07 15:42:20 +01003436 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003437#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003438#ifdef OPENSSL_ALPN_NEGOTIATED
3439 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3440#endif
Willy Tarreau80aca902013-01-07 15:42:20 +01003441 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3442 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3443 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_CBIN, SMP_USE_L5CLI },
3444 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreau7875d092012-09-10 08:20:03 +02003445 { NULL, NULL, 0, 0, 0 },
3446}};
3447
3448/* Note: must not be declared <const> as its list will be overwritten.
3449 * Please take care of keeping this list alphabetically sorted.
3450 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003451static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003452 { "ssl_c_i_dn", NULL, pat_parse_str, pat_match_str },
3453 { "ssl_c_key_alg", NULL, pat_parse_str, pat_match_str },
3454 { "ssl_c_notafter", NULL, pat_parse_str, pat_match_str },
3455 { "ssl_c_notbefore", NULL, pat_parse_str, pat_match_str },
3456 { "ssl_c_sig_alg", NULL, pat_parse_str, pat_match_str },
3457 { "ssl_c_s_dn", NULL, pat_parse_str, pat_match_str },
3458 { "ssl_c_serial", NULL, pat_parse_bin, pat_match_bin },
3459 { "ssl_f_i_dn", NULL, pat_parse_str, pat_match_str },
3460 { "ssl_f_key_alg", NULL, pat_parse_str, pat_match_str },
3461 { "ssl_f_notafter", NULL, pat_parse_str, pat_match_str },
3462 { "ssl_f_notbefore", NULL, pat_parse_str, pat_match_str },
3463 { "ssl_f_sig_alg", NULL, pat_parse_str, pat_match_str },
3464 { "ssl_f_s_dn", NULL, pat_parse_str, pat_match_str },
3465 { "ssl_f_serial", NULL, pat_parse_bin, pat_match_bin },
3466 { "ssl_fc_cipher", NULL, pat_parse_str, pat_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003467#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003468 { "ssl_fc_npn", NULL, pat_parse_str, pat_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003469#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003470#ifdef OPENSSL_ALPN_NEGOTIATED
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003471 { "ssl_fc_alpn", NULL, pat_parse_str, pat_match_str },
Willy Tarreauab861d32013-04-02 02:30:41 +02003472#endif
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003473 { "ssl_fc_protocol", NULL, pat_parse_str, pat_match_str },
3474 { "ssl_fc_sni", "ssl_fc_sni", pat_parse_str, pat_match_str },
3475 { "ssl_fc_sni_end", "ssl_fc_sni", pat_parse_str, pat_match_end },
3476 { "ssl_fc_sni_reg", "ssl_fc_sni", pat_parse_reg, pat_match_reg },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01003477 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02003478}};
3479
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003480/* Note: must not be declared <const> as its list will be overwritten.
3481 * Please take care of keeping this list alphabetically sorted, doing so helps
3482 * all code contributors.
3483 * Optional keywords are also declared with a NULL ->parse() function so that
3484 * the config parser can report an appropriate error when a known keyword was
3485 * not enabled.
3486 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02003487static struct bind_kw_list bind_kws = { "SSL", { }, {
Willy Tarreauab861d32013-04-02 02:30:41 +02003488 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003489 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003490 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
3491 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003492 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003493 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
3494 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003495 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003496 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003497 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
3498 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
3499 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
3500 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02003501 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
3502 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
3503 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
3504 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003505 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003506 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003507 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003508 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003509 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003510 { NULL, NULL, 0 },
3511}};
Emeric Brun46591952012-05-18 15:47:34 +02003512
Willy Tarreau92faadf2012-10-10 23:04:25 +02003513/* Note: must not be declared <const> as its list will be overwritten.
3514 * Please take care of keeping this list alphabetically sorted, doing so helps
3515 * all code contributors.
3516 * Optional keywords are also declared with a NULL ->parse() function so that
3517 * the config parser can report an appropriate error when a known keyword was
3518 * not enabled.
3519 */
3520static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02003521 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003522 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
3523 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02003524 { "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 +02003525 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003526 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
3527 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
3528 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
3529 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
3530 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
3531 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
3532 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
3533 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02003534 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003535 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02003536 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Evan Broderbe554312013-06-27 00:05:25 -07003537 { "verifyhost", srv_parse_verifyhost, 1, 0 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02003538 { NULL, NULL, 0, 0 },
3539}};
3540
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003541/* transport-layer operations for SSL sockets */
3542struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02003543 .snd_buf = ssl_sock_from_buf,
3544 .rcv_buf = ssl_sock_to_buf,
3545 .rcv_pipe = NULL,
3546 .snd_pipe = NULL,
3547 .shutr = NULL,
3548 .shutw = ssl_sock_shutw,
3549 .close = ssl_sock_close,
3550 .init = ssl_sock_init,
3551};
3552
3553__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02003554static void __ssl_sock_init(void)
3555{
Emeric Brun46591952012-05-18 15:47:34 +02003556 STACK_OF(SSL_COMP)* cm;
3557
3558 SSL_library_init();
3559 cm = SSL_COMP_get_compression_methods();
3560 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02003561 sample_register_fetches(&sample_fetch_keywords);
3562 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003563 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02003564 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02003565}
3566
3567/*
3568 * Local variables:
3569 * c-indent-level: 8
3570 * c-basic-offset: 8
3571 * End:
3572 */