blob: 9396cbd524bf5814f2b2729359ce9b04115a5d08 [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 Tarreau20879a02012-12-03 16:32:10 +01001100 if (global.maxsslconn && sslconns >= global.maxsslconn) {
1101 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02001102 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001103 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001104
Emeric Brun46591952012-05-18 15:47:34 +02001105 /* If it is in client mode initiate SSL session
1106 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001107 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001108 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001109 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001110 if (!conn->xprt_ctx) {
1111 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001112 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001113 }
Emeric Brun46591952012-05-18 15:47:34 +02001114
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001115 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001116 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1117 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001118
1119 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001120 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001121
Evan Broderbe554312013-06-27 00:05:25 -07001122 /* set connection pointer */
1123 SSL_set_app_data(conn->xprt_ctx, conn);
1124
Emeric Brun46591952012-05-18 15:47:34 +02001125 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001126 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001127
1128 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001129 return 0;
1130 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001131 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001132 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001133 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001134 if (!conn->xprt_ctx) {
1135 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001136 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001137 }
Emeric Brun46591952012-05-18 15:47:34 +02001138
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001139 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001140
1141 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001142 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001143
Emeric Brune1f38db2012-09-03 20:36:47 +02001144 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001145 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +02001146
Emeric Brun46591952012-05-18 15:47:34 +02001147 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001148 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001149
1150 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001151 return 0;
1152 }
1153 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01001154 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02001155 return -1;
1156}
1157
1158
1159/* This is the callback which is used when an SSL handshake is pending. It
1160 * updates the FD status if it wants some polling before being called again.
1161 * It returns 0 if it fails in a fatal way or needs to poll to go further,
1162 * otherwise it returns non-zero and removes itself from the connection's
1163 * flags (the bit is provided in <flag> by the caller).
1164 */
1165int ssl_sock_handshake(struct connection *conn, unsigned int flag)
1166{
1167 int ret;
1168
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001169 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001170 goto out_error;
1171
Emeric Brun674b7432012-11-08 19:21:55 +01001172 /* If we use SSL_do_handshake to process a reneg initiated by
1173 * the remote peer, it sometimes returns SSL_ERROR_SSL.
1174 * Usually SSL_write and SSL_read are used and process implicitly
1175 * the reneg handshake.
1176 * Here we use SSL_peek as a workaround for reneg.
1177 */
1178 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
1179 char c;
1180
1181 ret = SSL_peek(conn->xprt_ctx, &c, 1);
1182 if (ret <= 0) {
1183 /* handshake may have not been completed, let's find why */
1184 ret = SSL_get_error(conn->xprt_ctx, ret);
1185 if (ret == SSL_ERROR_WANT_WRITE) {
1186 /* SSL handshake needs to write, L4 connection may not be ready */
1187 __conn_sock_stop_recv(conn);
1188 __conn_sock_poll_send(conn);
1189 return 0;
1190 }
1191 else if (ret == SSL_ERROR_WANT_READ) {
1192 /* handshake may have been completed but we have
1193 * no more data to read.
1194 */
1195 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
1196 ret = 1;
1197 goto reneg_ok;
1198 }
1199 /* SSL handshake needs to read, L4 connection is ready */
1200 if (conn->flags & CO_FL_WAIT_L4_CONN)
1201 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1202 __conn_sock_stop_send(conn);
1203 __conn_sock_poll_recv(conn);
1204 return 0;
1205 }
1206 else if (ret == SSL_ERROR_SYSCALL) {
1207 /* if errno is null, then connection was successfully established */
1208 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1209 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001210 if (!conn->err_code) {
1211 if (!((SSL *)conn->xprt_ctx)->packet_length)
1212 if (!errno)
1213 conn->err_code = CO_ER_SSL_EMPTY;
1214 else
1215 conn->err_code = CO_ER_SSL_ABORT;
1216 else
1217 conn->err_code = CO_ER_SSL_HANDSHAKE;
1218 }
Emeric Brun674b7432012-11-08 19:21:55 +01001219 goto out_error;
1220 }
1221 else {
1222 /* Fail on all other handshake errors */
1223 /* Note: OpenSSL may leave unread bytes in the socket's
1224 * buffer, causing an RST to be emitted upon close() on
1225 * TCP sockets. We first try to drain possibly pending
1226 * data to avoid this as much as possible.
1227 */
Willy Tarreau2b57cb82013-06-10 19:56:38 +02001228 if (conn->ctrl && conn->ctrl->drain)
1229 conn->ctrl->drain(conn->t.sock.fd);
Willy Tarreau20879a02012-12-03 16:32:10 +01001230 if (!conn->err_code)
1231 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01001232 goto out_error;
1233 }
1234 }
1235 /* read some data: consider handshake completed */
1236 goto reneg_ok;
1237 }
1238
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001239 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001240 if (ret != 1) {
1241 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001242 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001243
1244 if (ret == SSL_ERROR_WANT_WRITE) {
1245 /* SSL handshake needs to write, L4 connection may not be ready */
1246 __conn_sock_stop_recv(conn);
1247 __conn_sock_poll_send(conn);
1248 return 0;
1249 }
1250 else if (ret == SSL_ERROR_WANT_READ) {
1251 /* SSL handshake needs to read, L4 connection is ready */
1252 if (conn->flags & CO_FL_WAIT_L4_CONN)
1253 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1254 __conn_sock_stop_send(conn);
1255 __conn_sock_poll_recv(conn);
1256 return 0;
1257 }
Willy Tarreau89230192012-09-28 20:22:13 +02001258 else if (ret == SSL_ERROR_SYSCALL) {
1259 /* if errno is null, then connection was successfully established */
1260 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1261 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001262
1263 if (!((SSL *)conn->xprt_ctx)->packet_length)
1264 if (!errno)
1265 conn->err_code = CO_ER_SSL_EMPTY;
1266 else
1267 conn->err_code = CO_ER_SSL_ABORT;
1268 else
1269 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +02001270 goto out_error;
1271 }
Emeric Brun46591952012-05-18 15:47:34 +02001272 else {
1273 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02001274 /* Note: OpenSSL may leave unread bytes in the socket's
1275 * buffer, causing an RST to be emitted upon close() on
1276 * TCP sockets. We first try to drain possibly pending
1277 * data to avoid this as much as possible.
1278 */
Willy Tarreau2b57cb82013-06-10 19:56:38 +02001279 if (conn->ctrl && conn->ctrl->drain)
1280 conn->ctrl->drain(conn->t.sock.fd);
Willy Tarreau20879a02012-12-03 16:32:10 +01001281 if (!conn->err_code)
1282 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001283 goto out_error;
1284 }
1285 }
1286
Emeric Brun674b7432012-11-08 19:21:55 +01001287reneg_ok:
1288
Emeric Brun46591952012-05-18 15:47:34 +02001289 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001290 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001291 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +02001292 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001293 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1294 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001295
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001296 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001297 }
1298 }
1299
1300 /* The connection is now established at both layers, it's time to leave */
1301 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1302 return 1;
1303
1304 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001305 /* Clear openssl global errors stack */
1306 ERR_clear_error();
1307
Emeric Brun9fa89732012-10-04 17:09:56 +02001308 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001309 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1310 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1311 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001312 }
1313
Emeric Brun46591952012-05-18 15:47:34 +02001314 /* Fail on all other handshake errors */
1315 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001316 if (!conn->err_code)
1317 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001318 return 0;
1319}
1320
1321/* Receive up to <count> bytes from connection <conn>'s socket and store them
1322 * into buffer <buf>. The caller must ensure that <count> is always smaller
1323 * than the buffer's size. Only one call to recv() is performed, unless the
1324 * buffer wraps, in which case a second call may be performed. The connection's
1325 * flags are updated with whatever special event is detected (error, read0,
1326 * empty). The caller is responsible for taking care of those events and
1327 * avoiding the call if inappropriate. The function does not call the
1328 * connection's polling update function, so the caller is responsible for this.
1329 */
1330static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1331{
1332 int ret, done = 0;
1333 int try = count;
1334
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001335 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001336 goto out_error;
1337
1338 if (conn->flags & CO_FL_HANDSHAKE)
1339 /* a handshake was requested */
1340 return 0;
1341
1342 /* compute the maximum block size we can read at once. */
1343 if (buffer_empty(buf)) {
1344 /* let's realign the buffer to optimize I/O */
1345 buf->p = buf->data;
1346 }
1347 else if (buf->data + buf->o < buf->p &&
1348 buf->p + buf->i < buf->data + buf->size) {
1349 /* remaining space wraps at the end, with a moving limit */
1350 if (try > buf->data + buf->size - (buf->p + buf->i))
1351 try = buf->data + buf->size - (buf->p + buf->i);
1352 }
1353
1354 /* read the largest possible block. For this, we perform only one call
1355 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1356 * in which case we accept to do it once again. A new attempt is made on
1357 * EINTR too.
1358 */
1359 while (try) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001360 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001361 if (conn->flags & CO_FL_ERROR) {
1362 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001363 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001364 }
Emeric Brun46591952012-05-18 15:47:34 +02001365 if (ret > 0) {
1366 buf->i += ret;
1367 done += ret;
1368 if (ret < try)
1369 break;
1370 count -= ret;
1371 try = count;
1372 }
1373 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001374 ret = SSL_get_error(conn->xprt_ctx, ret);
1375 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001376 /* error on protocol or underlying transport */
1377 if ((ret != SSL_ERROR_SYSCALL)
1378 || (errno && (errno != EAGAIN)))
1379 conn->flags |= CO_FL_ERROR;
1380
Emeric Brun644cde02012-12-14 11:21:13 +01001381 /* Clear openssl global errors stack */
1382 ERR_clear_error();
1383 }
Emeric Brun46591952012-05-18 15:47:34 +02001384 goto read0;
1385 }
1386 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001387 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001388 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001389 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001390 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001391 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001392 break;
1393 }
1394 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001395 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1396 /* handshake is running, and it may need to re-enable read */
1397 conn->flags |= CO_FL_SSL_WAIT_HS;
1398 __conn_sock_want_recv(conn);
1399 break;
1400 }
Emeric Brun46591952012-05-18 15:47:34 +02001401 /* we need to poll for retry a read later */
1402 __conn_data_poll_recv(conn);
1403 break;
1404 }
1405 /* otherwise it's a real error */
1406 goto out_error;
1407 }
1408 }
1409 return done;
1410
1411 read0:
1412 conn_sock_read0(conn);
1413 return done;
1414 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001415 /* Clear openssl global errors stack */
1416 ERR_clear_error();
1417
Emeric Brun46591952012-05-18 15:47:34 +02001418 conn->flags |= CO_FL_ERROR;
1419 return done;
1420}
1421
1422
1423/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1424 * <flags> may contain MSG_MORE to make the system hold on without sending
1425 * data too fast, but this flag is ignored at the moment.
1426 * Only one call to send() is performed, unless the buffer wraps, in which case
1427 * a second call may be performed. The connection's flags are updated with
1428 * whatever special event is detected (error, empty). The caller is responsible
1429 * for taking care of those events and avoiding the call if inappropriate. The
1430 * function does not call the connection's polling update function, so the caller
1431 * is responsible for this.
1432 */
1433static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1434{
1435 int ret, try, done;
1436
1437 done = 0;
1438
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001439 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001440 goto out_error;
1441
1442 if (conn->flags & CO_FL_HANDSHAKE)
1443 /* a handshake was requested */
1444 return 0;
1445
1446 /* send the largest possible block. For this we perform only one call
1447 * to send() unless the buffer wraps and we exactly fill the first hunk,
1448 * in which case we accept to do it once again.
1449 */
1450 while (buf->o) {
Kevin Hestercad82342013-05-30 15:12:41 -07001451 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01001452
1453 if (global.tune.ssl_max_record && try > global.tune.ssl_max_record)
1454 try = global.tune.ssl_max_record;
1455
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001456 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001457 if (conn->flags & CO_FL_ERROR) {
1458 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001459 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001460 }
Emeric Brun46591952012-05-18 15:47:34 +02001461 if (ret > 0) {
1462 buf->o -= ret;
1463 done += ret;
1464
Willy Tarreau5fb38032012-12-16 19:39:09 +01001465 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001466 /* optimize data alignment in the buffer */
1467 buf->p = buf->data;
1468
1469 /* if the system buffer is full, don't insist */
1470 if (ret < try)
1471 break;
1472 }
1473 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001474 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001475 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001476 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1477 /* handshake is running, and it may need to re-enable write */
1478 conn->flags |= CO_FL_SSL_WAIT_HS;
1479 __conn_sock_want_send(conn);
1480 break;
1481 }
Emeric Brun46591952012-05-18 15:47:34 +02001482 /* we need to poll to retry a write later */
1483 __conn_data_poll_send(conn);
1484 break;
1485 }
1486 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001487 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001488 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001489 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001490 break;
1491 }
1492 goto out_error;
1493 }
1494 }
1495 return done;
1496
1497 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001498 /* Clear openssl global errors stack */
1499 ERR_clear_error();
1500
Emeric Brun46591952012-05-18 15:47:34 +02001501 conn->flags |= CO_FL_ERROR;
1502 return done;
1503}
1504
Emeric Brun46591952012-05-18 15:47:34 +02001505static void ssl_sock_close(struct connection *conn) {
1506
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001507 if (conn->xprt_ctx) {
1508 SSL_free(conn->xprt_ctx);
1509 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001510 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001511 }
Emeric Brun46591952012-05-18 15:47:34 +02001512}
1513
1514/* This function tries to perform a clean shutdown on an SSL connection, and in
1515 * any case, flags the connection as reusable if no handshake was in progress.
1516 */
1517static void ssl_sock_shutw(struct connection *conn, int clean)
1518{
1519 if (conn->flags & CO_FL_HANDSHAKE)
1520 return;
1521 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001522 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1523 /* Clear openssl global errors stack */
1524 ERR_clear_error();
1525 }
Emeric Brun46591952012-05-18 15:47:34 +02001526
1527 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001528 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001529}
1530
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001531/* used for logging, may be changed for a sample fetch later */
1532const char *ssl_sock_get_cipher_name(struct connection *conn)
1533{
1534 if (!conn->xprt && !conn->xprt_ctx)
1535 return NULL;
1536 return SSL_get_cipher_name(conn->xprt_ctx);
1537}
1538
1539/* used for logging, may be changed for a sample fetch later */
1540const char *ssl_sock_get_proto_version(struct connection *conn)
1541{
1542 if (!conn->xprt && !conn->xprt_ctx)
1543 return NULL;
1544 return SSL_get_version(conn->xprt_ctx);
1545}
1546
Willy Tarreau8d598402012-10-22 17:58:39 +02001547/* Extract a serial from a cert, and copy it to a chunk.
1548 * Returns 1 if serial is found and copied, 0 if no serial found and
1549 * -1 if output is not large enough.
1550 */
1551static int
1552ssl_sock_get_serial(X509 *crt, struct chunk *out)
1553{
1554 ASN1_INTEGER *serial;
1555
1556 serial = X509_get_serialNumber(crt);
1557 if (!serial)
1558 return 0;
1559
1560 if (out->size < serial->length)
1561 return -1;
1562
1563 memcpy(out->str, serial->data, serial->length);
1564 out->len = serial->length;
1565 return 1;
1566}
1567
Emeric Brunce5ad802012-10-22 14:11:22 +02001568
1569/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1570 * Returns 1 if serial is found and copied, 0 if no valid time found
1571 * and -1 if output is not large enough.
1572 */
1573static int
1574ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1575{
1576 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1577 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1578
1579 if (gentm->length < 12)
1580 return 0;
1581 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1582 return 0;
1583 if (out->size < gentm->length-2)
1584 return -1;
1585
1586 memcpy(out->str, gentm->data+2, gentm->length-2);
1587 out->len = gentm->length-2;
1588 return 1;
1589 }
1590 else if (tm->type == V_ASN1_UTCTIME) {
1591 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1592
1593 if (utctm->length < 10)
1594 return 0;
1595 if (utctm->data[0] >= 0x35)
1596 return 0;
1597 if (out->size < utctm->length)
1598 return -1;
1599
1600 memcpy(out->str, utctm->data, utctm->length);
1601 out->len = utctm->length;
1602 return 1;
1603 }
1604
1605 return 0;
1606}
1607
Emeric Brun87855892012-10-17 17:39:35 +02001608/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1609 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1610 */
1611static int
1612ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1613{
1614 X509_NAME_ENTRY *ne;
1615 int i, j, n;
1616 int cur = 0;
1617 const char *s;
1618 char tmp[128];
1619
1620 out->len = 0;
1621 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1622 if (pos < 0)
1623 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1624 else
1625 j = i;
1626
1627 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1628 n = OBJ_obj2nid(ne->object);
1629 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1630 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1631 s = tmp;
1632 }
1633
1634 if (chunk_strcasecmp(entry, s) != 0)
1635 continue;
1636
1637 if (pos < 0)
1638 cur--;
1639 else
1640 cur++;
1641
1642 if (cur != pos)
1643 continue;
1644
1645 if (ne->value->length > out->size)
1646 return -1;
1647
1648 memcpy(out->str, ne->value->data, ne->value->length);
1649 out->len = ne->value->length;
1650 return 1;
1651 }
1652
1653 return 0;
1654
1655}
1656
1657/* Extract and format full DN from a X509_NAME and copy result into a chunk
1658 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1659 */
1660static int
1661ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1662{
1663 X509_NAME_ENTRY *ne;
1664 int i, n, ln;
1665 int l = 0;
1666 const char *s;
1667 char *p;
1668 char tmp[128];
1669
1670 out->len = 0;
1671 p = out->str;
1672 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1673 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1674 n = OBJ_obj2nid(ne->object);
1675 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1676 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1677 s = tmp;
1678 }
1679 ln = strlen(s);
1680
1681 l += 1 + ln + 1 + ne->value->length;
1682 if (l > out->size)
1683 return -1;
1684 out->len = l;
1685
1686 *(p++)='/';
1687 memcpy(p, s, ln);
1688 p += ln;
1689 *(p++)='=';
1690 memcpy(p, ne->value->data, ne->value->length);
1691 p += ne->value->length;
1692 }
1693
1694 if (!out->len)
1695 return 0;
1696
1697 return 1;
1698}
1699
Willy Tarreau7875d092012-09-10 08:20:03 +02001700/***** Below are some sample fetching functions for ACL/patterns *****/
1701
Emeric Brune64aef12012-09-21 13:15:06 +02001702/* boolean, returns true if client cert was present */
1703static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001704smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001705 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brune64aef12012-09-21 13:15:06 +02001706{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001707 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001708 return 0;
1709
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001710 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001711 smp->flags |= SMP_F_MAY_CHANGE;
1712 return 0;
1713 }
1714
1715 smp->flags = 0;
1716 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001717 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001718
1719 return 1;
1720}
1721
Willy Tarreau8d598402012-10-22 17:58:39 +02001722/* bin, returns serial in a binary chunk */
1723static int
1724smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001725 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02001726{
1727 X509 *crt = NULL;
1728 int ret = 0;
1729 struct chunk *smp_trash;
1730
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001731 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001732 return 0;
1733
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001734 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001735 smp->flags |= SMP_F_MAY_CHANGE;
1736 return 0;
1737 }
1738
1739 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001740 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001741 if (!crt)
1742 goto out;
1743
Willy Tarreau47ca5452012-12-23 20:22:19 +01001744 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001745 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1746 goto out;
1747
1748 smp->data.str = *smp_trash;
1749 smp->type = SMP_T_BIN;
1750 ret = 1;
1751out:
1752 if (crt)
1753 X509_free(crt);
1754 return ret;
1755}
Emeric Brune64aef12012-09-21 13:15:06 +02001756
James Votha051b4a2013-05-14 20:37:59 +02001757/* bin, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk */
1758static int
1759smp_fetch_ssl_c_sha1(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001760 const struct arg *args, struct sample *smp, const char *kw)
James Votha051b4a2013-05-14 20:37:59 +02001761{
1762 X509 *crt = NULL;
1763 const EVP_MD *digest;
1764 int ret = 0;
1765 struct chunk *smp_trash;
1766
1767 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
1768 return 0;
1769
1770 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
1771 smp->flags |= SMP_F_MAY_CHANGE;
1772 return 0;
1773 }
1774
1775 /* SSL_get_peer_certificate, it increase X509 * ref count */
1776 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
1777 if (!crt)
1778 goto out;
1779
1780 smp_trash = get_trash_chunk();
1781 digest = EVP_sha1();
1782 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
1783
1784 smp->data.str = *smp_trash;
1785 smp->type = SMP_T_BIN;
1786 ret = 1;
1787out:
1788 if (crt)
1789 X509_free(crt);
1790 return ret;
1791}
1792
Emeric Brunce5ad802012-10-22 14:11:22 +02001793/*str, returns notafter date in ASN1_UTCTIME format */
1794static int
1795smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001796 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001797{
1798 X509 *crt = NULL;
1799 int ret = 0;
1800 struct chunk *smp_trash;
1801
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001802 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001803 return 0;
1804
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001805 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001806 smp->flags |= SMP_F_MAY_CHANGE;
1807 return 0;
1808 }
1809
1810 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001811 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001812 if (!crt)
1813 goto out;
1814
Willy Tarreau47ca5452012-12-23 20:22:19 +01001815 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001816 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1817 goto out;
1818
1819 smp->data.str = *smp_trash;
1820 smp->type = SMP_T_STR;
1821 ret = 1;
1822out:
1823 if (crt)
1824 X509_free(crt);
1825 return ret;
1826}
1827
Emeric Brun87855892012-10-17 17:39:35 +02001828/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1829static int
1830smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001831 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02001832{
1833 X509 *crt = NULL;
1834 X509_NAME *name;
1835 int ret = 0;
1836 struct chunk *smp_trash;
1837
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001838 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001839 return 0;
1840
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001841 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001842 smp->flags |= SMP_F_MAY_CHANGE;
1843 return 0;
1844 }
1845
1846 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001847 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001848 if (!crt)
1849 goto out;
1850
1851 name = X509_get_issuer_name(crt);
1852 if (!name)
1853 goto out;
1854
Willy Tarreau47ca5452012-12-23 20:22:19 +01001855 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001856 if (args && args[0].type == ARGT_STR) {
1857 int pos = 1;
1858
1859 if (args[1].type == ARGT_SINT)
1860 pos = args[1].data.sint;
1861 else if (args[1].type == ARGT_UINT)
1862 pos =(int)args[1].data.uint;
1863
1864 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1865 goto out;
1866 }
1867 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1868 goto out;
1869
1870 smp->type = SMP_T_STR;
1871 smp->data.str = *smp_trash;
1872 ret = 1;
1873out:
1874 if (crt)
1875 X509_free(crt);
1876 return ret;
1877}
1878
Emeric Brunce5ad802012-10-22 14:11:22 +02001879/*str, returns notbefore date in ASN1_UTCTIME format */
1880static int
1881smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001882 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001883{
1884 X509 *crt = NULL;
1885 int ret = 0;
1886 struct chunk *smp_trash;
1887
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001888 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001889 return 0;
1890
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001891 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001892 smp->flags |= SMP_F_MAY_CHANGE;
1893 return 0;
1894 }
1895
1896 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001897 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001898 if (!crt)
1899 goto out;
1900
Willy Tarreau47ca5452012-12-23 20:22:19 +01001901 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001902 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1903 goto out;
1904
1905 smp->data.str = *smp_trash;
1906 smp->type = SMP_T_STR;
1907 ret = 1;
1908out:
1909 if (crt)
1910 X509_free(crt);
1911 return ret;
1912}
1913
Emeric Brun87855892012-10-17 17:39:35 +02001914/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1915static int
1916smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001917 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02001918{
1919 X509 *crt = NULL;
1920 X509_NAME *name;
1921 int ret = 0;
1922 struct chunk *smp_trash;
1923
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001924 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001925 return 0;
1926
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001927 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001928 smp->flags |= SMP_F_MAY_CHANGE;
1929 return 0;
1930 }
1931
1932 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001933 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001934 if (!crt)
1935 goto out;
1936
1937 name = X509_get_subject_name(crt);
1938 if (!name)
1939 goto out;
1940
Willy Tarreau47ca5452012-12-23 20:22:19 +01001941 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001942 if (args && args[0].type == ARGT_STR) {
1943 int pos = 1;
1944
1945 if (args[1].type == ARGT_SINT)
1946 pos = args[1].data.sint;
1947 else if (args[1].type == ARGT_UINT)
1948 pos =(int)args[1].data.uint;
1949
1950 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1951 goto out;
1952 }
1953 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1954 goto out;
1955
1956 smp->type = SMP_T_STR;
1957 smp->data.str = *smp_trash;
1958 ret = 1;
1959out:
1960 if (crt)
1961 X509_free(crt);
1962 return ret;
1963}
Emeric Brun9143d372012-12-20 15:44:16 +01001964
1965/* integer, returns true if current session use a client certificate */
1966static int
1967smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001968 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun9143d372012-12-20 15:44:16 +01001969{
1970 X509 *crt;
1971
1972 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
1973 return 0;
1974
1975 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
1976 smp->flags |= SMP_F_MAY_CHANGE;
1977 return 0;
1978 }
1979
1980 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
1981 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
1982 if (crt) {
1983 X509_free(crt);
1984 }
1985
1986 smp->type = SMP_T_BOOL;
1987 smp->data.uint = (crt != NULL);
1988 return 1;
1989}
1990
Emeric Bruna7359fd2012-10-17 15:03:11 +02001991/* integer, returns the client certificate version */
1992static int
1993smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001994 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001995{
1996 X509 *crt;
1997
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001998 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001999 return 0;
2000
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002001 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002002 smp->flags |= SMP_F_MAY_CHANGE;
2003 return 0;
2004 }
2005
2006 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002007 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002008 if (!crt)
2009 return 0;
2010
2011 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2012 X509_free(crt);
2013 smp->type = SMP_T_UINT;
2014
2015 return 1;
2016}
2017
Emeric Brun7f56e742012-10-19 18:15:40 +02002018/* str, returns the client certificate sig alg */
2019static int
2020smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002021 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002022{
2023 X509 *crt;
2024 int nid;
2025
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002026 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02002027 return 0;
2028
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002029 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002030 smp->flags |= SMP_F_MAY_CHANGE;
2031 return 0;
2032 }
2033
2034 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002035 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002036 if (!crt)
2037 return 0;
2038
2039 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2040
2041 smp->data.str.str = (char *)OBJ_nid2sn(nid);
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002042 if (!smp->data.str.str) {
2043 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02002044 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002045 }
Emeric Brun7f56e742012-10-19 18:15:40 +02002046
2047 smp->type = SMP_T_CSTR;
2048 smp->data.str.len = strlen(smp->data.str.str);
2049 X509_free(crt);
2050
2051 return 1;
2052}
2053
Emeric Brun521a0112012-10-22 12:22:55 +02002054/* str, returns the client certificate key alg */
2055static int
2056smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002057 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002058{
2059 X509 *crt;
2060 int nid;
2061
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002062 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002063 return 0;
2064
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002065 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002066 smp->flags |= SMP_F_MAY_CHANGE;
2067 return 0;
2068 }
2069
2070 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002071 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002072 if (!crt)
2073 return 0;
2074
2075 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2076
2077 smp->data.str.str = (char *)OBJ_nid2sn(nid);
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002078 if (!smp->data.str.str) {
2079 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02002080 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002081 }
Emeric Brun521a0112012-10-22 12:22:55 +02002082
2083 smp->type = SMP_T_CSTR;
2084 smp->data.str.len = strlen(smp->data.str.str);
2085 X509_free(crt);
2086
2087 return 1;
2088}
2089
Emeric Brun2525b6b2012-10-18 15:59:43 +02002090/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02002091static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002092smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002093 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002094{
2095 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002096 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02002097 return 1;
2098}
2099
Emeric Brun2525b6b2012-10-18 15:59:43 +02002100/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02002101static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002102smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002103 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002104{
2105#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2106 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002107 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock) &&
2108 l4->si[0].conn->xprt_ctx &&
2109 SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02002110 return 1;
2111#else
2112 return 0;
2113#endif
2114}
2115
Willy Tarreau8d598402012-10-22 17:58:39 +02002116/* bin, returns serial in a binary chunk */
2117static int
2118smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002119 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02002120{
2121 X509 *crt = NULL;
2122 int ret = 0;
2123 struct chunk *smp_trash;
2124
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002125 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02002126 return 0;
2127
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002128 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02002129 smp->flags |= SMP_F_MAY_CHANGE;
2130 return 0;
2131 }
2132
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002133 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02002134 if (!crt)
2135 goto out;
2136
Willy Tarreau47ca5452012-12-23 20:22:19 +01002137 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02002138 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
2139 goto out;
2140
2141 smp->data.str = *smp_trash;
2142 smp->type = SMP_T_BIN;
2143 ret = 1;
2144out:
2145 return ret;
2146}
Emeric Brunce5ad802012-10-22 14:11:22 +02002147/*str, returns notafter date in ASN1_UTCTIME format */
2148static int
2149smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002150 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002151{
2152 X509 *crt = NULL;
2153 int ret = 0;
2154 struct chunk *smp_trash;
2155
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002156 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02002157 return 0;
2158
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002159 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002160 smp->flags |= SMP_F_MAY_CHANGE;
2161 return 0;
2162 }
2163
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002164 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002165 if (!crt)
2166 goto out;
2167
Willy Tarreau47ca5452012-12-23 20:22:19 +01002168 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002169 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
2170 goto out;
2171
2172 smp->data.str = *smp_trash;
2173 smp->type = SMP_T_STR;
2174 ret = 1;
2175out:
2176 return ret;
2177}
2178
2179/*str, returns notbefore date in ASN1_UTCTIME format */
2180static int
2181smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002182 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002183{
2184 X509 *crt = NULL;
2185 int ret = 0;
2186 struct chunk *smp_trash;
2187
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002188 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02002189 return 0;
2190
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002191 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002192 smp->flags |= SMP_F_MAY_CHANGE;
2193 return 0;
2194 }
2195
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002196 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002197 if (!crt)
2198 goto out;
2199
Willy Tarreau47ca5452012-12-23 20:22:19 +01002200 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002201 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
2202 goto out;
2203
2204 smp->data.str = *smp_trash;
2205 smp->type = SMP_T_STR;
2206 ret = 1;
2207out:
2208 return ret;
2209}
Willy Tarreau8d598402012-10-22 17:58:39 +02002210
Emeric Bruna7359fd2012-10-17 15:03:11 +02002211/* integer, returns the frontend certificate version */
2212static int
2213smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002214 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002215{
2216 X509 *crt;
2217
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002218 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002219 return 0;
2220
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002221 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002222 smp->flags |= SMP_F_MAY_CHANGE;
2223 return 0;
2224 }
2225
2226 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002227 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002228 if (!crt)
2229 return 0;
2230
2231 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2232 smp->type = SMP_T_UINT;
2233
2234 return 1;
2235}
2236
Emeric Brun7f56e742012-10-19 18:15:40 +02002237/* str, returns the client certificate sig alg */
2238static int
2239smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002240 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002241{
2242 X509 *crt;
2243 int nid;
2244
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002245 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02002246 return 0;
2247
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002248 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002249 smp->flags |= SMP_F_MAY_CHANGE;
2250 return 0;
2251 }
2252
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002253 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002254 if (!crt)
2255 return 0;
2256
2257 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2258
2259 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2260 if (!smp->data.str.str)
2261 return 0;
2262
2263 smp->type = SMP_T_CSTR;
2264 smp->data.str.len = strlen(smp->data.str.str);
2265
2266 return 1;
2267}
2268
Emeric Brun521a0112012-10-22 12:22:55 +02002269/* str, returns the client certificate key alg */
2270static int
2271smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002272 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002273{
2274 X509 *crt;
2275 int nid;
2276
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002277 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002278 return 0;
2279
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002280 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002281 smp->flags |= SMP_F_MAY_CHANGE;
2282 return 0;
2283 }
2284
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002285 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002286 if (!crt)
2287 return 0;
2288
2289 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2290
2291 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2292 if (!smp->data.str.str)
2293 return 0;
2294
2295 smp->type = SMP_T_CSTR;
2296 smp->data.str.len = strlen(smp->data.str.str);
2297
2298 return 1;
2299}
2300
Emeric Brun87855892012-10-17 17:39:35 +02002301/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2302static int
2303smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002304 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002305{
2306 X509 *crt = NULL;
2307 X509_NAME *name;
2308 int ret = 0;
2309 struct chunk *smp_trash;
2310
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002311 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002312 return 0;
2313
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002314 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002315 smp->flags |= SMP_F_MAY_CHANGE;
2316 return 0;
2317 }
2318
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002319 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002320 if (!crt)
2321 goto out;
2322
2323 name = X509_get_issuer_name(crt);
2324 if (!name)
2325 goto out;
2326
Willy Tarreau47ca5452012-12-23 20:22:19 +01002327 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002328 if (args && args[0].type == ARGT_STR) {
2329 int pos = 1;
2330
2331 if (args[1].type == ARGT_SINT)
2332 pos = args[1].data.sint;
2333 else if (args[1].type == ARGT_UINT)
2334 pos =(int)args[1].data.uint;
2335
2336 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2337 goto out;
2338 }
2339 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2340 goto out;
2341
2342 smp->type = SMP_T_STR;
2343 smp->data.str = *smp_trash;
2344 ret = 1;
2345out:
2346 return ret;
2347}
2348
2349/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2350static int
2351smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002352 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002353{
2354 X509 *crt = NULL;
2355 X509_NAME *name;
2356 int ret = 0;
2357 struct chunk *smp_trash;
2358
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002359 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002360 return 0;
2361
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002362 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002363 smp->flags |= SMP_F_MAY_CHANGE;
2364 return 0;
2365 }
2366
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002367 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002368 if (!crt)
2369 goto out;
2370
2371 name = X509_get_subject_name(crt);
2372 if (!name)
2373 goto out;
2374
Willy Tarreau47ca5452012-12-23 20:22:19 +01002375 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002376 if (args && args[0].type == ARGT_STR) {
2377 int pos = 1;
2378
2379 if (args[1].type == ARGT_SINT)
2380 pos = args[1].data.sint;
2381 else if (args[1].type == ARGT_UINT)
2382 pos =(int)args[1].data.uint;
2383
2384 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2385 goto out;
2386 }
2387 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2388 goto out;
2389
2390 smp->type = SMP_T_STR;
2391 smp->data.str = *smp_trash;
2392 ret = 1;
2393out:
2394 return ret;
2395}
2396
Emeric Brun589fcad2012-10-16 14:13:26 +02002397static int
2398smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002399 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002400{
2401 smp->flags = 0;
2402
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002403 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002404 return 0;
2405
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002406 smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002407 if (!smp->data.str.str)
2408 return 0;
2409
2410 smp->type = SMP_T_CSTR;
2411 smp->data.str.len = strlen(smp->data.str.str);
2412
2413 return 1;
2414}
2415
2416static int
2417smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002418 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002419{
2420 smp->flags = 0;
2421
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002422 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002423 return 0;
2424
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002425 if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
Emeric Brun589fcad2012-10-16 14:13:26 +02002426 return 0;
2427
2428 smp->type = SMP_T_UINT;
2429
2430 return 1;
2431}
2432
2433static int
2434smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002435 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002436{
2437 smp->flags = 0;
2438
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002439 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002440 return 0;
2441
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002442 smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002443 if (!smp->data.uint)
2444 return 0;
2445
2446 smp->type = SMP_T_UINT;
2447
2448 return 1;
2449}
2450
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002451#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002452static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002453smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002454 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002455{
Willy Tarreaua33c6542012-10-15 13:19:06 +02002456 smp->flags = 0;
2457 smp->type = SMP_T_CSTR;
2458
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002459 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002460 return 0;
2461
2462 smp->data.str.str = NULL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002463 SSL_get0_next_proto_negotiated(l4->si[0].conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002464 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2465
2466 if (!smp->data.str.str)
2467 return 0;
2468
2469 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002470}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002471#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002472
Willy Tarreauab861d32013-04-02 02:30:41 +02002473#ifdef OPENSSL_ALPN_NEGOTIATED
2474static int
2475smp_fetch_ssl_fc_alpn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002476 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreauab861d32013-04-02 02:30:41 +02002477{
2478 smp->flags = 0;
2479 smp->type = SMP_T_CSTR;
2480
2481 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
2482 return 0;
2483
2484 smp->data.str.str = NULL;
2485 SSL_get0_alpn_negotiated(l4->si[0].conn->xprt_ctx,
2486 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2487
2488 if (!smp->data.str.str)
2489 return 0;
2490
2491 return 1;
2492}
2493#endif
2494
Willy Tarreaua33c6542012-10-15 13:19:06 +02002495static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002496smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002497 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002498{
2499 smp->flags = 0;
2500
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002501 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002502 return 0;
2503
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002504 smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002505 if (!smp->data.str.str)
2506 return 0;
2507
2508 smp->type = SMP_T_CSTR;
2509 smp->data.str.len = strlen(smp->data.str.str);
2510
2511 return 1;
2512}
2513
2514static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002515smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002516 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunfe68f682012-10-16 14:59:28 +02002517{
2518#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2519 SSL_SESSION *sess;
2520
2521 smp->flags = 0;
2522 smp->type = SMP_T_CBIN;
2523
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002524 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunfe68f682012-10-16 14:59:28 +02002525 return 0;
2526
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002527 sess = SSL_get_session(l4->si[0].conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002528 if (!sess)
2529 return 0;
2530
2531 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2532 if (!smp->data.str.str || !&smp->data.str.len)
2533 return 0;
2534
2535 return 1;
2536#else
2537 return 0;
2538#endif
2539}
2540
2541static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002542smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002543 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002544{
2545#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2546 smp->flags = 0;
2547 smp->type = SMP_T_CSTR;
2548
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002549 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau7875d092012-09-10 08:20:03 +02002550 return 0;
2551
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002552 smp->data.str.str = (char *)SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau3e394c92012-09-14 23:56:58 +02002553 if (!smp->data.str.str)
2554 return 0;
2555
Willy Tarreau7875d092012-09-10 08:20:03 +02002556 smp->data.str.len = strlen(smp->data.str.str);
2557 return 1;
2558#else
2559 return 0;
2560#endif
2561}
2562
Emeric Brun2525b6b2012-10-18 15:59:43 +02002563/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002564static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002565smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002566 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002567{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002568 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002569 return 0;
2570
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002571 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002572 smp->flags = SMP_F_MAY_CHANGE;
2573 return 0;
2574 }
2575
2576 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002577 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002578 smp->flags = 0;
2579
2580 return 1;
2581}
2582
Emeric Brun2525b6b2012-10-18 15:59:43 +02002583/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002584static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002585smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002586 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002587{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002588 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002589 return 0;
2590
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002591 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002592 smp->flags = SMP_F_MAY_CHANGE;
2593 return 0;
2594 }
2595
2596 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002597 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002598 smp->flags = 0;
2599
2600 return 1;
2601}
2602
Emeric Brun2525b6b2012-10-18 15:59:43 +02002603/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002604static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002605smp_fetch_ssl_c_err(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)
Emeric Brunf282a812012-09-21 15:27:54 +02002607{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002608 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002609 return 0;
2610
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002611 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002612 smp->flags = SMP_F_MAY_CHANGE;
2613 return 0;
2614 }
2615
2616 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002617 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002618 smp->flags = 0;
2619
2620 return 1;
2621}
2622
Emeric Brun2525b6b2012-10-18 15:59:43 +02002623/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002624static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002625smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002626 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002627{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002628 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002629 return 0;
2630
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002631 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002632 smp->flags = SMP_F_MAY_CHANGE;
2633 return 0;
2634 }
2635
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002636 if (!l4->si[0].conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002637 return 0;
2638
2639 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002640 smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002641 smp->flags = 0;
2642
2643 return 1;
2644}
2645
Emeric Brunfb510ea2012-10-05 12:00:26 +02002646/* parse the "ca-file" bind keyword */
2647static 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 +02002648{
2649 if (!*args[cur_arg + 1]) {
2650 if (err)
2651 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2652 return ERR_ALERT | ERR_FATAL;
2653 }
2654
Emeric Brunef42d922012-10-11 16:11:36 +02002655 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2656 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2657 else
2658 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002659
Emeric Brund94b3fe2012-09-20 18:23:56 +02002660 return 0;
2661}
2662
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002663/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002664static 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 +02002665{
2666 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002667 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002668 return ERR_ALERT | ERR_FATAL;
2669 }
2670
Emeric Brun76d88952012-10-05 15:47:31 +02002671 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002672 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002673 return 0;
2674}
2675
2676/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002677static 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 +02002678{
Willy Tarreau38011032013-08-13 16:59:39 +02002679 char path[MAXPATHLEN];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002680 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002681 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002682 return ERR_ALERT | ERR_FATAL;
2683 }
2684
Emeric Brunc8e8d122012-10-02 18:42:10 +02002685 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
Willy Tarreau38011032013-08-13 16:59:39 +02002686 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02002687 memprintf(err, "'%s' : path too long", args[cur_arg]);
2688 return ERR_ALERT | ERR_FATAL;
2689 }
2690 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2691 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2692 return ERR_ALERT | ERR_FATAL;
2693
2694 return 0;
2695 }
2696
Willy Tarreau4348fad2012-09-20 16:48:07 +02002697 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002698 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002699
2700 return 0;
2701}
2702
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002703/* parse the "crt-list" bind keyword */
2704static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2705{
2706 if (!*args[cur_arg + 1]) {
2707 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
2708 return ERR_ALERT | ERR_FATAL;
2709 }
2710
Willy Tarreauad1731d2013-04-02 17:35:58 +02002711 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
2712 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002713 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02002714 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002715
2716 return 0;
2717}
2718
Emeric Brunfb510ea2012-10-05 12:00:26 +02002719/* parse the "crl-file" bind keyword */
2720static 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 +02002721{
Emeric Brun051cdab2012-10-02 19:25:50 +02002722#ifndef X509_V_FLAG_CRL_CHECK
2723 if (err)
2724 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2725 return ERR_ALERT | ERR_FATAL;
2726#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002727 if (!*args[cur_arg + 1]) {
2728 if (err)
2729 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2730 return ERR_ALERT | ERR_FATAL;
2731 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002732
Emeric Brunef42d922012-10-11 16:11:36 +02002733 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2734 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2735 else
2736 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002737
Emeric Brun2b58d042012-09-20 17:10:03 +02002738 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002739#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002740}
2741
2742/* parse the "ecdhe" bind keyword keywords */
2743static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2744{
2745#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2746 if (err)
2747 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2748 return ERR_ALERT | ERR_FATAL;
2749#elif defined(OPENSSL_NO_ECDH)
2750 if (err)
2751 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2752 return ERR_ALERT | ERR_FATAL;
2753#else
2754 if (!*args[cur_arg + 1]) {
2755 if (err)
2756 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2757 return ERR_ALERT | ERR_FATAL;
2758 }
2759
2760 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002761
2762 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002763#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002764}
2765
Emeric Brun81c00f02012-09-21 14:31:21 +02002766/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2767static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2768{
2769 int code;
2770 char *p = args[cur_arg + 1];
2771 unsigned long long *ignerr = &conf->crt_ignerr;
2772
2773 if (!*p) {
2774 if (err)
2775 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2776 return ERR_ALERT | ERR_FATAL;
2777 }
2778
2779 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2780 ignerr = &conf->ca_ignerr;
2781
2782 if (strcmp(p, "all") == 0) {
2783 *ignerr = ~0ULL;
2784 return 0;
2785 }
2786
2787 while (p) {
2788 code = atoi(p);
2789 if ((code <= 0) || (code > 63)) {
2790 if (err)
2791 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2792 args[cur_arg], code, args[cur_arg + 1]);
2793 return ERR_ALERT | ERR_FATAL;
2794 }
2795 *ignerr |= 1ULL << code;
2796 p = strchr(p, ',');
2797 if (p)
2798 p++;
2799 }
2800
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002801 return 0;
2802}
2803
2804/* parse the "force-sslv3" bind keyword */
2805static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2806{
2807 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2808 return 0;
2809}
2810
2811/* parse the "force-tlsv10" bind keyword */
2812static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2813{
2814 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002815 return 0;
2816}
2817
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002818/* parse the "force-tlsv11" bind keyword */
2819static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2820{
2821#if SSL_OP_NO_TLSv1_1
2822 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
2823 return 0;
2824#else
2825 if (err)
2826 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
2827 return ERR_ALERT | ERR_FATAL;
2828#endif
2829}
2830
2831/* parse the "force-tlsv12" bind keyword */
2832static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2833{
2834#if SSL_OP_NO_TLSv1_2
2835 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
2836 return 0;
2837#else
2838 if (err)
2839 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
2840 return ERR_ALERT | ERR_FATAL;
2841#endif
2842}
2843
2844
Emeric Brun2d0c4822012-10-02 13:45:20 +02002845/* parse the "no-tls-tickets" bind keyword */
2846static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2847{
Emeric Brun89675492012-10-05 13:48:26 +02002848 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02002849 return 0;
2850}
2851
Emeric Brun2d0c4822012-10-02 13:45:20 +02002852
Emeric Brun9b3009b2012-10-05 11:55:06 +02002853/* parse the "no-sslv3" bind keyword */
2854static 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 +02002855{
Emeric Brun89675492012-10-05 13:48:26 +02002856 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002857 return 0;
2858}
2859
Emeric Brun9b3009b2012-10-05 11:55:06 +02002860/* parse the "no-tlsv10" bind keyword */
2861static 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 +02002862{
Emeric Brun89675492012-10-05 13:48:26 +02002863 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002864 return 0;
2865}
2866
Emeric Brun9b3009b2012-10-05 11:55:06 +02002867/* parse the "no-tlsv11" bind keyword */
2868static 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 +02002869{
Emeric Brun89675492012-10-05 13:48:26 +02002870 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002871 return 0;
2872}
2873
Emeric Brun9b3009b2012-10-05 11:55:06 +02002874/* parse the "no-tlsv12" bind keyword */
2875static 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 +02002876{
Emeric Brun89675492012-10-05 13:48:26 +02002877 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002878 return 0;
2879}
2880
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002881/* parse the "npn" bind keyword */
2882static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2883{
2884#ifdef OPENSSL_NPN_NEGOTIATED
2885 char *p1, *p2;
2886
2887 if (!*args[cur_arg + 1]) {
2888 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
2889 return ERR_ALERT | ERR_FATAL;
2890 }
2891
2892 free(conf->npn_str);
2893
2894 /* the NPN string is built as a suite of (<len> <name>)* */
2895 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
2896 conf->npn_str = calloc(1, conf->npn_len);
2897 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
2898
2899 /* replace commas with the name length */
2900 p1 = conf->npn_str;
2901 p2 = p1 + 1;
2902 while (1) {
2903 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
2904 if (!p2)
2905 p2 = p1 + 1 + strlen(p1 + 1);
2906
2907 if (p2 - (p1 + 1) > 255) {
2908 *p2 = '\0';
2909 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2910 return ERR_ALERT | ERR_FATAL;
2911 }
2912
2913 *p1 = p2 - (p1 + 1);
2914 p1 = p2;
2915
2916 if (!*p2)
2917 break;
2918
2919 *(p2++) = '\0';
2920 }
2921 return 0;
2922#else
2923 if (err)
2924 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
2925 return ERR_ALERT | ERR_FATAL;
2926#endif
2927}
2928
Willy Tarreauab861d32013-04-02 02:30:41 +02002929/* parse the "alpn" bind keyword */
2930static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2931{
2932#ifdef OPENSSL_ALPN_NEGOTIATED
2933 char *p1, *p2;
2934
2935 if (!*args[cur_arg + 1]) {
2936 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
2937 return ERR_ALERT | ERR_FATAL;
2938 }
2939
2940 free(conf->alpn_str);
2941
2942 /* the ALPN string is built as a suite of (<len> <name>)* */
2943 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
2944 conf->alpn_str = calloc(1, conf->alpn_len);
2945 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
2946
2947 /* replace commas with the name length */
2948 p1 = conf->alpn_str;
2949 p2 = p1 + 1;
2950 while (1) {
2951 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
2952 if (!p2)
2953 p2 = p1 + 1 + strlen(p1 + 1);
2954
2955 if (p2 - (p1 + 1) > 255) {
2956 *p2 = '\0';
2957 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2958 return ERR_ALERT | ERR_FATAL;
2959 }
2960
2961 *p1 = p2 - (p1 + 1);
2962 p1 = p2;
2963
2964 if (!*p2)
2965 break;
2966
2967 *(p2++) = '\0';
2968 }
2969 return 0;
2970#else
2971 if (err)
2972 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
2973 return ERR_ALERT | ERR_FATAL;
2974#endif
2975}
2976
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002977/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002978static 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 +02002979{
Willy Tarreau81796be2012-09-22 19:11:47 +02002980 struct listener *l;
2981
Willy Tarreau4348fad2012-09-20 16:48:07 +02002982 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02002983
2984 if (global.listen_default_ciphers && !conf->ciphers)
2985 conf->ciphers = strdup(global.listen_default_ciphers);
2986
Willy Tarreau81796be2012-09-22 19:11:47 +02002987 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002988 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02002989
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002990 return 0;
2991}
2992
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002993/* parse the "strict-sni" bind keyword */
2994static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2995{
2996 conf->strict_sni = 1;
2997 return 0;
2998}
2999
Emeric Brund94b3fe2012-09-20 18:23:56 +02003000/* parse the "verify" bind keyword */
3001static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3002{
3003 if (!*args[cur_arg + 1]) {
3004 if (err)
3005 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
3006 return ERR_ALERT | ERR_FATAL;
3007 }
3008
3009 if (strcmp(args[cur_arg + 1], "none") == 0)
3010 conf->verify = SSL_VERIFY_NONE;
3011 else if (strcmp(args[cur_arg + 1], "optional") == 0)
3012 conf->verify = SSL_VERIFY_PEER;
3013 else if (strcmp(args[cur_arg + 1], "required") == 0)
3014 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
3015 else {
3016 if (err)
3017 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
3018 args[cur_arg], args[cur_arg + 1]);
3019 return ERR_ALERT | ERR_FATAL;
3020 }
3021
3022 return 0;
3023}
3024
Willy Tarreau92faadf2012-10-10 23:04:25 +02003025/************** "server" keywords ****************/
3026
Emeric Brunef42d922012-10-11 16:11:36 +02003027/* parse the "ca-file" server keyword */
3028static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3029{
3030 if (!*args[*cur_arg + 1]) {
3031 if (err)
3032 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
3033 return ERR_ALERT | ERR_FATAL;
3034 }
3035
3036 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3037 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3038 else
3039 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
3040
3041 return 0;
3042}
3043
Willy Tarreau92faadf2012-10-10 23:04:25 +02003044/* parse the "check-ssl" server keyword */
3045static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3046{
3047 newsrv->check.use_ssl = 1;
3048 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3049 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3050 return 0;
3051}
3052
3053/* parse the "ciphers" server keyword */
3054static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3055{
3056 if (!*args[*cur_arg + 1]) {
3057 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
3058 return ERR_ALERT | ERR_FATAL;
3059 }
3060
3061 free(newsrv->ssl_ctx.ciphers);
3062 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
3063 return 0;
3064}
3065
Emeric Brunef42d922012-10-11 16:11:36 +02003066/* parse the "crl-file" server keyword */
3067static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3068{
3069#ifndef X509_V_FLAG_CRL_CHECK
3070 if (err)
3071 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
3072 return ERR_ALERT | ERR_FATAL;
3073#else
3074 if (!*args[*cur_arg + 1]) {
3075 if (err)
3076 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
3077 return ERR_ALERT | ERR_FATAL;
3078 }
3079
3080 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3081 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3082 else
3083 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
3084
3085 return 0;
3086#endif
3087}
3088
Emeric Bruna7aa3092012-10-26 12:58:00 +02003089/* parse the "crt" server keyword */
3090static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3091{
3092 if (!*args[*cur_arg + 1]) {
3093 if (err)
3094 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
3095 return ERR_ALERT | ERR_FATAL;
3096 }
3097
3098 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
3099 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3100 else
3101 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
3102
3103 return 0;
3104}
Emeric Brunef42d922012-10-11 16:11:36 +02003105
Willy Tarreau92faadf2012-10-10 23:04:25 +02003106/* parse the "force-sslv3" server keyword */
3107static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3108{
3109 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
3110 return 0;
3111}
3112
3113/* parse the "force-tlsv10" server keyword */
3114static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3115{
3116 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
3117 return 0;
3118}
3119
3120/* parse the "force-tlsv11" server keyword */
3121static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3122{
3123#if SSL_OP_NO_TLSv1_1
3124 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
3125 return 0;
3126#else
3127 if (err)
3128 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
3129 return ERR_ALERT | ERR_FATAL;
3130#endif
3131}
3132
3133/* parse the "force-tlsv12" server keyword */
3134static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3135{
3136#if SSL_OP_NO_TLSv1_2
3137 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
3138 return 0;
3139#else
3140 if (err)
3141 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
3142 return ERR_ALERT | ERR_FATAL;
3143#endif
3144}
3145
3146/* parse the "no-sslv3" server keyword */
3147static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3148{
3149 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
3150 return 0;
3151}
3152
3153/* parse the "no-tlsv10" server keyword */
3154static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3155{
3156 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
3157 return 0;
3158}
3159
3160/* parse the "no-tlsv11" server keyword */
3161static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3162{
3163 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
3164 return 0;
3165}
3166
3167/* parse the "no-tlsv12" server keyword */
3168static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3169{
3170 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
3171 return 0;
3172}
3173
Emeric Brunf9c5c472012-10-11 15:28:34 +02003174/* parse the "no-tls-tickets" server keyword */
3175static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3176{
3177 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
3178 return 0;
3179}
3180
Willy Tarreau92faadf2012-10-10 23:04:25 +02003181/* parse the "ssl" server keyword */
3182static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3183{
3184 newsrv->use_ssl = 1;
3185 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3186 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3187 return 0;
3188}
3189
Emeric Brunef42d922012-10-11 16:11:36 +02003190/* parse the "verify" server keyword */
3191static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3192{
3193 if (!*args[*cur_arg + 1]) {
3194 if (err)
3195 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
3196 return ERR_ALERT | ERR_FATAL;
3197 }
3198
3199 if (strcmp(args[*cur_arg + 1], "none") == 0)
3200 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
3201 else if (strcmp(args[*cur_arg + 1], "required") == 0)
3202 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
3203 else {
3204 if (err)
3205 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
3206 args[*cur_arg], args[*cur_arg + 1]);
3207 return ERR_ALERT | ERR_FATAL;
3208 }
3209
Evan Broderbe554312013-06-27 00:05:25 -07003210 return 0;
3211}
3212
3213/* parse the "verifyhost" server keyword */
3214static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3215{
3216 if (!*args[*cur_arg + 1]) {
3217 if (err)
3218 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
3219 return ERR_ALERT | ERR_FATAL;
3220 }
3221
3222 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
3223
Emeric Brunef42d922012-10-11 16:11:36 +02003224 return 0;
3225}
3226
Willy Tarreau7875d092012-09-10 08:20:03 +02003227/* Note: must not be declared <const> as its list will be overwritten.
3228 * Please take care of keeping this list alphabetically sorted.
3229 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003230static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Willy Tarreau80aca902013-01-07 15:42:20 +01003231 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3232 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3233 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3234 { "ssl_c_i_dn", smp_fetch_ssl_c_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3235 { "ssl_c_key_alg", smp_fetch_ssl_c_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3236 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3237 { "ssl_c_notbefore", smp_fetch_ssl_c_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3238 { "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3239 { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3240 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
James Votha051b4a2013-05-14 20:37:59 +02003241 { "ssl_c_sha1", smp_fetch_ssl_c_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01003242 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3243 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3244 { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3245 { "ssl_f_i_dn", smp_fetch_ssl_f_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3246 { "ssl_f_key_alg", smp_fetch_ssl_f_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3247 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3248 { "ssl_f_notbefore", smp_fetch_ssl_f_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3249 { "ssl_f_sig_alg", smp_fetch_ssl_f_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3250 { "ssl_f_s_dn", smp_fetch_ssl_f_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3251 { "ssl_f_serial", smp_fetch_ssl_f_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3252 { "ssl_f_version", smp_fetch_ssl_f_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3253 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3254 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3255 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3256 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3257 { "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 +02003258#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau80aca902013-01-07 15:42:20 +01003259 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003260#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003261#ifdef OPENSSL_ALPN_NEGOTIATED
3262 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3263#endif
Willy Tarreau80aca902013-01-07 15:42:20 +01003264 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3265 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3266 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_CBIN, SMP_USE_L5CLI },
3267 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreau7875d092012-09-10 08:20:03 +02003268 { NULL, NULL, 0, 0, 0 },
3269}};
3270
3271/* Note: must not be declared <const> as its list will be overwritten.
3272 * Please take care of keeping this list alphabetically sorted.
3273 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003274static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003275 { "ssl_c_i_dn", NULL, pat_parse_str, pat_match_str },
3276 { "ssl_c_key_alg", NULL, pat_parse_str, pat_match_str },
3277 { "ssl_c_notafter", NULL, pat_parse_str, pat_match_str },
3278 { "ssl_c_notbefore", NULL, pat_parse_str, pat_match_str },
3279 { "ssl_c_sig_alg", NULL, pat_parse_str, pat_match_str },
3280 { "ssl_c_s_dn", NULL, pat_parse_str, pat_match_str },
3281 { "ssl_c_serial", NULL, pat_parse_bin, pat_match_bin },
3282 { "ssl_f_i_dn", NULL, pat_parse_str, pat_match_str },
3283 { "ssl_f_key_alg", NULL, pat_parse_str, pat_match_str },
3284 { "ssl_f_notafter", NULL, pat_parse_str, pat_match_str },
3285 { "ssl_f_notbefore", NULL, pat_parse_str, pat_match_str },
3286 { "ssl_f_sig_alg", NULL, pat_parse_str, pat_match_str },
3287 { "ssl_f_s_dn", NULL, pat_parse_str, pat_match_str },
3288 { "ssl_f_serial", NULL, pat_parse_bin, pat_match_bin },
3289 { "ssl_fc_cipher", NULL, pat_parse_str, pat_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003290#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003291 { "ssl_fc_npn", NULL, pat_parse_str, pat_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003292#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003293#ifdef OPENSSL_ALPN_NEGOTIATED
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003294 { "ssl_fc_alpn", NULL, pat_parse_str, pat_match_str },
Willy Tarreauab861d32013-04-02 02:30:41 +02003295#endif
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003296 { "ssl_fc_protocol", NULL, pat_parse_str, pat_match_str },
3297 { "ssl_fc_sni", "ssl_fc_sni", pat_parse_str, pat_match_str },
3298 { "ssl_fc_sni_end", "ssl_fc_sni", pat_parse_str, pat_match_end },
3299 { "ssl_fc_sni_reg", "ssl_fc_sni", pat_parse_reg, pat_match_reg },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01003300 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02003301}};
3302
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003303/* Note: must not be declared <const> as its list will be overwritten.
3304 * Please take care of keeping this list alphabetically sorted, doing so helps
3305 * all code contributors.
3306 * Optional keywords are also declared with a NULL ->parse() function so that
3307 * the config parser can report an appropriate error when a known keyword was
3308 * not enabled.
3309 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02003310static struct bind_kw_list bind_kws = { "SSL", { }, {
Willy Tarreauab861d32013-04-02 02:30:41 +02003311 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003312 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003313 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
3314 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003315 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003316 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
3317 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003318 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003319 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003320 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
3321 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
3322 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
3323 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02003324 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
3325 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
3326 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
3327 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003328 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003329 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003330 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003331 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003332 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003333 { NULL, NULL, 0 },
3334}};
Emeric Brun46591952012-05-18 15:47:34 +02003335
Willy Tarreau92faadf2012-10-10 23:04:25 +02003336/* Note: must not be declared <const> as its list will be overwritten.
3337 * Please take care of keeping this list alphabetically sorted, doing so helps
3338 * all code contributors.
3339 * Optional keywords are also declared with a NULL ->parse() function so that
3340 * the config parser can report an appropriate error when a known keyword was
3341 * not enabled.
3342 */
3343static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02003344 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003345 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
3346 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02003347 { "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 +02003348 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003349 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
3350 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
3351 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
3352 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
3353 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
3354 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
3355 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
3356 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02003357 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003358 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02003359 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Evan Broderbe554312013-06-27 00:05:25 -07003360 { "verifyhost", srv_parse_verifyhost, 1, 0 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02003361 { NULL, NULL, 0, 0 },
3362}};
3363
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003364/* transport-layer operations for SSL sockets */
3365struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02003366 .snd_buf = ssl_sock_from_buf,
3367 .rcv_buf = ssl_sock_to_buf,
3368 .rcv_pipe = NULL,
3369 .snd_pipe = NULL,
3370 .shutr = NULL,
3371 .shutw = ssl_sock_shutw,
3372 .close = ssl_sock_close,
3373 .init = ssl_sock_init,
3374};
3375
3376__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02003377static void __ssl_sock_init(void)
3378{
Emeric Brun46591952012-05-18 15:47:34 +02003379 STACK_OF(SSL_COMP)* cm;
3380
3381 SSL_library_init();
3382 cm = SSL_COMP_get_compression_methods();
3383 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02003384 sample_register_fetches(&sample_fetch_keywords);
3385 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003386 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02003387 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02003388}
3389
3390/*
3391 * Local variables:
3392 * c-indent-level: 8
3393 * c-basic-offset: 8
3394 * End:
3395 */