blob: 330f47a9adbee1411dabaebd29105ca76212fa92 [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>
Emeric Brun46591952012-05-18 15:47:34 +020046
47#include <common/buffer.h>
48#include <common/compat.h>
49#include <common/config.h>
50#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020051#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020052#include <common/standard.h>
53#include <common/ticks.h>
54#include <common/time.h>
55
Emeric Brunfc0421f2012-09-07 17:30:07 +020056#include <ebsttree.h>
57
58#include <types/global.h>
59#include <types/ssl_sock.h>
60
Willy Tarreau7875d092012-09-10 08:20:03 +020061#include <proto/acl.h>
62#include <proto/arg.h>
Emeric Brun46591952012-05-18 15:47:34 +020063#include <proto/connection.h>
64#include <proto/fd.h>
65#include <proto/freq_ctr.h>
66#include <proto/frontend.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020067#include <proto/listener.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020068#include <proto/server.h>
Emeric Brun46591952012-05-18 15:47:34 +020069#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +020070#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +020072#include <proto/ssl_sock.h>
73#include <proto/task.h>
74
Emeric Brune64aef12012-09-21 13:15:06 +020075#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brunf282a812012-09-21 15:27:54 +020076/* bits 0xFFFF0000 are reserved to store verify errors */
77
78/* Verify errors macros */
79#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
80#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
81#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
82
83#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
84#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
85#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +020086
Willy Tarreau403edff2012-09-06 11:58:37 +020087static int sslconns = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +020088
89void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
90{
91 struct connection *conn = (struct connection *)SSL_get_app_data(ssl);
92 (void)ret; /* shut gcc stupid warning */
93
94 if (where & SSL_CB_HANDSHAKE_START) {
95 /* Disable renegotiation (CVE-2009-3555) */
96 if (conn->flags & CO_FL_CONNECTED)
97 conn->flags |= CO_FL_ERROR;
98 }
Emeric Brunfc0421f2012-09-07 17:30:07 +020099}
100
Emeric Brune64aef12012-09-21 13:15:06 +0200101/* Callback is called for each certificate of the chain during a verify
102 ok is set to 1 if preverify detect no error on current certificate.
103 Returns 0 to break the handshake, 1 otherwise. */
104int ssl_sock_verifycbk(int ok, X509_STORE_CTX *x_store)
105{
106 SSL *ssl;
107 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +0200108 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +0200109
110 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
111 conn = (struct connection *)SSL_get_app_data(ssl);
112
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200113 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +0200114
Emeric Brun81c00f02012-09-21 14:31:21 +0200115 if (ok) /* no errors */
116 return ok;
117
118 depth = X509_STORE_CTX_get_error_depth(x_store);
119 err = X509_STORE_CTX_get_error(x_store);
120
121 /* check if CA error needs to be ignored */
122 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200123 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
124 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
125 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +0200126 }
127
Emeric Brun81c00f02012-09-21 14:31:21 +0200128 if (target_client(&conn->target)->bind_conf->ca_ignerr & (1ULL << err))
129 return 1;
130
131 return 0;
132 }
133
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200134 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
135 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +0200136
Emeric Brun81c00f02012-09-21 14:31:21 +0200137 /* check if certificate error needs to be ignored */
138 if (target_client(&conn->target)->bind_conf->crt_ignerr & (1ULL << err))
139 return 1;
140
141 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +0200142}
143
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200144#ifdef OPENSSL_NPN_NEGOTIATED
145/* This callback is used so that the server advertises the list of
146 * negociable protocols for NPN.
147 */
148static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
149 unsigned int *len, void *arg)
150{
151 struct bind_conf *conf = arg;
152
153 *data = (const unsigned char *)conf->npn_str;
154 *len = conf->npn_len;
155 return SSL_TLSEXT_ERR_OK;
156}
157#endif
158
Emeric Brunfc0421f2012-09-07 17:30:07 +0200159#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
160/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
161 * warning when no match is found, which implies the default (first) cert
162 * will keep being used.
163 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200164static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, struct bind_conf *s)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200165{
166 const char *servername;
167 const char *wildp = NULL;
168 struct ebmb_node *node;
169 int i;
170 (void)al; /* shut gcc stupid warning */
171
172 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
173 if (!servername)
174 return SSL_TLSEXT_ERR_NOACK;
175
176 for (i = 0; i < trashlen; i++) {
177 if (!servername[i])
178 break;
179 trash[i] = tolower(servername[i]);
180 if (!wildp && (trash[i] == '.'))
181 wildp = &trash[i];
182 }
183 trash[i] = 0;
184
185 /* lookup in full qualified names */
186 node = ebst_lookup(&s->sni_ctx, trash);
187 if (!node) {
188 if (!wildp)
189 return SSL_TLSEXT_ERR_ALERT_WARNING;
190
191 /* lookup in full wildcards names */
192 node = ebst_lookup(&s->sni_w_ctx, wildp);
193 if (!node)
194 return SSL_TLSEXT_ERR_ALERT_WARNING;
195 }
196
197 /* switch ctx */
198 SSL_set_SSL_CTX(ssl, container_of(node, struct sni_ctx, name)->ctx);
199 return SSL_TLSEXT_ERR_OK;
200}
201#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
202
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200203#ifndef OPENSSL_NO_DH
204/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
205 if an error occured, and 0 if parameter not found. */
206int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
207{
208 int ret = -1;
209 BIO *in;
210 DH *dh = NULL;
211
212 in = BIO_new(BIO_s_file());
213 if (in == NULL)
214 goto end;
215
216 if (BIO_read_filename(in, file) <= 0)
217 goto end;
218
219 dh = PEM_read_bio_DHparams(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
220 if (dh) {
221 SSL_CTX_set_tmp_dh(ctx, dh);
222 ret = 1;
223 goto end;
224 }
225
226 ret = 0; /* DH params not found */
227end:
228 if (dh)
229 DH_free(dh);
230
231 if (in)
232 BIO_free(in);
233
234 return ret;
235}
236#endif
237
Emeric Brunfc0421f2012-09-07 17:30:07 +0200238/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
239 * an early error happens and the caller must call SSL_CTX_free() by itelf.
240 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200241int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200242{
243 BIO *in;
244 X509 *x = NULL, *ca;
245 int i, len, err;
246 int ret = -1;
247 int order = 0;
248 X509_NAME *xname;
249 char *str;
250 struct sni_ctx *sc;
251#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
252 STACK_OF(GENERAL_NAME) *names;
253#endif
254
255 in = BIO_new(BIO_s_file());
256 if (in == NULL)
257 goto end;
258
259 if (BIO_read_filename(in, file) <= 0)
260 goto end;
261
262 x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
263 if (x == NULL)
264 goto end;
265
266#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
267 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
268 if (names) {
269 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
270 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
271 if (name->type == GEN_DNS) {
272 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
273 if ((len = strlen(str))) {
274 int j;
275
276 if (*str != '*') {
277 sc = malloc(sizeof(struct sni_ctx) + len + 1);
278 for (j = 0; j < len; j++)
279 sc->name.key[j] = tolower(str[j]);
280 sc->name.key[len] = 0;
281 sc->order = order++;
282 sc->ctx = ctx;
283 ebst_insert(&s->sni_ctx, &sc->name);
284 }
285 else {
286 sc = malloc(sizeof(struct sni_ctx) + len);
287 for (j = 1; j < len; j++)
288 sc->name.key[j-1] = tolower(str[j]);
289 sc->name.key[len-1] = 0;
290 sc->order = order++;
291 sc->ctx = ctx;
292 ebst_insert(&s->sni_w_ctx, &sc->name);
293 }
294 }
295 OPENSSL_free(str);
296 }
297 }
298 }
299 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
300 }
301#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
302
303 xname = X509_get_subject_name(x);
304 i = -1;
305 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
306 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
307 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
308 if ((len = strlen(str))) {
309 int j;
310
311 if (*str != '*') {
312 sc = malloc(sizeof(struct sni_ctx) + len + 1);
313 for (j = 0; j < len; j++)
314 sc->name.key[j] = tolower(str[j]);
315 sc->name.key[len] = 0;
316 sc->order = order++;
317 sc->ctx = ctx;
318 ebst_insert(&s->sni_ctx, &sc->name);
319 }
320 else {
321 sc = malloc(sizeof(struct sni_ctx) + len);
322 for (j = 1; j < len; j++)
323 sc->name.key[j-1] = tolower(str[j]);
324 sc->name.key[len-1] = 0;
325 sc->order = order++;
326 sc->ctx = ctx;
327 ebst_insert(&s->sni_w_ctx, &sc->name);
328 }
329 }
330 OPENSSL_free(str);
331 }
332 }
333
334 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
335 if (!SSL_CTX_use_certificate(ctx, x))
336 goto end;
337
338 if (ctx->extra_certs != NULL) {
339 sk_X509_pop_free(ctx->extra_certs, X509_free);
340 ctx->extra_certs = NULL;
341 }
342
343 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata))) {
344 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
345 X509_free(ca);
346 goto end;
347 }
348 }
349
350 err = ERR_get_error();
351 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
352 /* we successfully reached the last cert in the file */
353 ret = 1;
354 }
355 ERR_clear_error();
356
357end:
358 if (x)
359 X509_free(x);
360
361 if (in)
362 BIO_free(in);
363
364 return ret;
365}
366
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200367static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200368{
369 int ret;
370 SSL_CTX *ctx;
371
372 ctx = SSL_CTX_new(SSLv23_server_method());
373 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200374 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
375 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200376 return 1;
377 }
378
379 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200380 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
381 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200382 SSL_CTX_free(ctx);
383 return 1;
384 }
385
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200386 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200387 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200388 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
389 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200390 if (ret < 0) /* serious error, must do that ourselves */
391 SSL_CTX_free(ctx);
392 return 1;
393 }
Emeric Brun61694ab2012-10-26 13:35:33 +0200394
395 if (SSL_CTX_check_private_key(ctx) <= 0) {
396 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
397 err && *err ? *err : "", path);
398 return 1;
399 }
400
Emeric Brunfc0421f2012-09-07 17:30:07 +0200401 /* we must not free the SSL_CTX anymore below, since it's already in
402 * the tree, so it will be discovered and cleaned in time.
403 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200404#ifndef OPENSSL_NO_DH
405 ret = ssl_sock_load_dh_params(ctx, path);
406 if (ret < 0) {
407 if (err)
408 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
409 *err ? *err : "", path);
410 return 1;
411 }
412#endif
413
Emeric Brunfc0421f2012-09-07 17:30:07 +0200414#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200415 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200416 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
417 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +0200418 return 1;
419 }
420#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200421 if (!bind_conf->default_ctx)
422 bind_conf->default_ctx = ctx;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200423
424 return 0;
425}
426
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200427int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200428{
429 struct dirent *de;
430 DIR *dir;
431 struct stat buf;
432 int pathlen = 0;
433 char *end, *fp;
434 int cfgerr = 0;
435
436 if (!(dir = opendir(path)))
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200437 return ssl_sock_load_cert_file(path, bind_conf, curproxy, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200438
439 /* strip trailing slashes, including first one */
440 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
441 *end = 0;
442
443 if (end >= path)
444 pathlen = end + 1 - path;
445 fp = malloc(pathlen + 1 + NAME_MAX + 1);
446
447 while ((de = readdir(dir))) {
448 snprintf(fp, pathlen + 1 + NAME_MAX + 1, "%s/%s", path, de->d_name);
449 if (stat(fp, &buf) != 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200450 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
451 err && *err ? *err : "", fp, strerror(errno));
Emeric Brunfc0421f2012-09-07 17:30:07 +0200452 cfgerr++;
453 continue;
454 }
455 if (!S_ISREG(buf.st_mode))
456 continue;
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200457 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, curproxy, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200458 }
459 free(fp);
460 closedir(dir);
461 return cfgerr;
462}
463
464#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
465#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
466#endif
467
468#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
469#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
470#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200471#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
472#define SSL_OP_SINGLE_ECDH_USE 0
473#endif
Emeric Brun2d0c4822012-10-02 13:45:20 +0200474#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
475#define SSL_OP_NO_TICKET 0
476#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200477#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
478#define SSL_OP_NO_COMPRESSION 0
479#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +0200480#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
481#define SSL_OP_NO_TLSv1_1 0
482#endif
483#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
484#define SSL_OP_NO_TLSv1_2 0
485#endif
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200486#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
487#define SSL_OP_SINGLE_DH_USE 0
488#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200489#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
490#define SSL_OP_SINGLE_ECDH_USE 0
491#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200492#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
493#define SSL_MODE_RELEASE_BUFFERS 0
494#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200495int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy *curproxy)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200496{
497 int cfgerr = 0;
498 int ssloptions =
499 SSL_OP_ALL | /* all known workarounds for bugs */
500 SSL_OP_NO_SSLv2 |
501 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200502 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +0200503 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +0200504 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
505 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200506 int sslmode =
507 SSL_MODE_ENABLE_PARTIAL_WRITE |
508 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
509 SSL_MODE_RELEASE_BUFFERS;
510
Emeric Brun89675492012-10-05 13:48:26 +0200511 if (bind_conf->ssl_options & BC_SSL_O_NO_SSLV3)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200512 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brun89675492012-10-05 13:48:26 +0200513 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV10)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200514 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun89675492012-10-05 13:48:26 +0200515 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV11)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200516 ssloptions |= SSL_OP_NO_TLSv1_1;
Emeric Brun89675492012-10-05 13:48:26 +0200517 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV12)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200518 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun89675492012-10-05 13:48:26 +0200519 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
Emeric Brun2d0c4822012-10-02 13:45:20 +0200520 ssloptions |= SSL_OP_NO_TICKET;
Emeric Brun2cb7ae52012-10-05 14:14:21 +0200521 if (bind_conf->ssl_options & BC_SSL_O_USE_SSLV3)
522 SSL_CTX_set_ssl_version(ctx, SSLv3_server_method());
523 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV10)
524 SSL_CTX_set_ssl_version(ctx, TLSv1_server_method());
525#if SSL_OP_NO_TLSv1_1
526 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV11)
527 SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method());
528#endif
529#if SSL_OP_NO_TLSv1_2
530 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV12)
531 SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method());
532#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200533
534 SSL_CTX_set_options(ctx, ssloptions);
535 SSL_CTX_set_mode(ctx, sslmode);
Emeric Brune64aef12012-09-21 13:15:06 +0200536 SSL_CTX_set_verify(ctx, bind_conf->verify ? bind_conf->verify : SSL_VERIFY_NONE, ssl_sock_verifycbk);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200537 if (bind_conf->verify & SSL_VERIFY_PEER) {
Emeric Brunfb510ea2012-10-05 12:00:26 +0200538 if (bind_conf->ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200539 /* load CAfile to verify */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200540 if (!SSL_CTX_load_verify_locations(ctx, bind_conf->ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200541 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200542 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200543 cfgerr++;
544 }
545 /* set CA names fo client cert request, function returns void */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200546 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(bind_conf->ca_file));
Emeric Brund94b3fe2012-09-20 18:23:56 +0200547 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200548#ifdef X509_V_FLAG_CRL_CHECK
Emeric Brunfb510ea2012-10-05 12:00:26 +0200549 if (bind_conf->crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200550 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
551
Emeric Brunfb510ea2012-10-05 12:00:26 +0200552 if (!store || !X509_STORE_load_locations(store, bind_conf->crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200553 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200554 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200555 cfgerr++;
556 }
Emeric Brun561e5742012-10-02 15:20:55 +0200557 else {
558 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
559 }
Emeric Brund94b3fe2012-09-20 18:23:56 +0200560 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200561#endif
Emeric Brund94b3fe2012-09-20 18:23:56 +0200562 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200563
564 shared_context_set_cache(ctx);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200565 if (bind_conf->ciphers &&
566 !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200567 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 +0200568 curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200569 cfgerr++;
570 }
571
572 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200573#ifdef OPENSSL_NPN_NEGOTIATED
574 if (bind_conf->npn_str)
575 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
576#endif
577
Emeric Brunfc0421f2012-09-07 17:30:07 +0200578#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
579 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200580 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200581#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200582#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
583 if (bind_conf->ecdhe) {
584 int i;
585 EC_KEY *ecdh;
586
587 i = OBJ_sn2nid(bind_conf->ecdhe);
588 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
589 Alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
590 curproxy->id, bind_conf->ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
591 cfgerr++;
592 }
593 else {
594 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
595 EC_KEY_free(ecdh);
596 }
597 }
598#endif
599
Emeric Brunfc0421f2012-09-07 17:30:07 +0200600 return cfgerr;
601}
602
Emeric Brun94324a42012-10-11 14:00:19 +0200603/* prepare ssl context from servers options. Returns an error count */
604int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
605{
606 int cfgerr = 0;
607 int options =
608 SSL_OP_ALL | /* all known workarounds for bugs */
609 SSL_OP_NO_SSLv2 |
610 SSL_OP_NO_COMPRESSION;
611 int mode =
612 SSL_MODE_ENABLE_PARTIAL_WRITE |
613 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
614 SSL_MODE_RELEASE_BUFFERS;
615
616 /* Initiate SSL context for current server */
617 srv->ssl_ctx.reused_sess = NULL;
618 if (srv->use_ssl)
619 srv->xprt = &ssl_sock;
620 if (srv->check.use_ssl)
621 srv->check.xprt = &ssl_sock;
622
623 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
624 if (!srv->ssl_ctx.ctx) {
625 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
626 proxy_type_str(curproxy), curproxy->id,
627 srv->id);
628 cfgerr++;
629 return cfgerr;
630 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200631 if (srv->ssl_ctx.client_crt) {
632 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
633 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
634 proxy_type_str(curproxy), curproxy->id,
635 srv->id, srv->ssl_ctx.client_crt);
636 cfgerr++;
637 }
638 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
639 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
640 proxy_type_str(curproxy), curproxy->id,
641 srv->id, srv->ssl_ctx.client_crt);
642 cfgerr++;
643 }
644 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
645 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
646 proxy_type_str(curproxy), curproxy->id,
647 srv->id, srv->ssl_ctx.client_crt);
648 cfgerr++;
649 }
650 }
Emeric Brun94324a42012-10-11 14:00:19 +0200651
652 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
653 options |= SSL_OP_NO_SSLv3;
654 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
655 options |= SSL_OP_NO_TLSv1;
656 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
657 options |= SSL_OP_NO_TLSv1_1;
658 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
659 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200660 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
661 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200662 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
663 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
664 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
665 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
666#if SSL_OP_NO_TLSv1_1
667 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
668 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
669#endif
670#if SSL_OP_NO_TLSv1_2
671 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
672 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
673#endif
674
675 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
676 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Emeric Brunef42d922012-10-11 16:11:36 +0200677 SSL_CTX_set_verify(srv->ssl_ctx.ctx, srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE, NULL);
678 if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
679 if (srv->ssl_ctx.ca_file) {
680 /* load CAfile to verify */
681 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
682 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
683 curproxy->id, srv->id,
684 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
685 cfgerr++;
686 }
687 }
688#ifdef X509_V_FLAG_CRL_CHECK
689 if (srv->ssl_ctx.crl_file) {
690 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
691
692 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
693 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
694 curproxy->id, srv->id,
695 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
696 cfgerr++;
697 }
698 else {
699 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
700 }
701 }
702#endif
703 }
704
Emeric Brun94324a42012-10-11 14:00:19 +0200705 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
706 if (srv->ssl_ctx.ciphers &&
707 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
708 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
709 curproxy->id, srv->id,
710 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
711 cfgerr++;
712 }
713
714 return cfgerr;
715}
716
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200717/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200718 * be NULL, in which case nothing is done. Returns the number of errors
719 * encountered.
720 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200721int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200722{
723 struct ebmb_node *node;
724 struct sni_ctx *sni;
725 int err = 0;
726
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200727 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200728 return 0;
729
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200730 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200731 while (node) {
732 sni = ebmb_entry(node, struct sni_ctx, name);
733 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200734 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200735 node = ebmb_next(node);
736 }
737
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200738 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200739 while (node) {
740 sni = ebmb_entry(node, struct sni_ctx, name);
741 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200742 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200743 node = ebmb_next(node);
744 }
745 return err;
746}
747
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200748/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200749 * be NULL, in which case nothing is done. The default_ctx is nullified too.
750 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200751void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200752{
753 struct ebmb_node *node, *back;
754 struct sni_ctx *sni;
755
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200756 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200757 return;
758
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200759 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200760 while (node) {
761 sni = ebmb_entry(node, struct sni_ctx, name);
762 back = ebmb_next(node);
763 ebmb_delete(node);
764 if (!sni->order) /* only free the CTX on its first occurrence */
765 SSL_CTX_free(sni->ctx);
766 free(sni);
767 node = back;
768 }
769
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200770 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200771 while (node) {
772 sni = ebmb_entry(node, struct sni_ctx, name);
773 back = ebmb_next(node);
774 ebmb_delete(node);
775 if (!sni->order) /* only free the CTX on its first occurrence */
776 SSL_CTX_free(sni->ctx);
777 free(sni);
778 node = back;
779 }
780
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200781 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +0200782}
783
Emeric Brun46591952012-05-18 15:47:34 +0200784/*
785 * This function is called if SSL * context is not yet allocated. The function
786 * is designed to be called before any other data-layer operation and sets the
787 * handshake flag on the connection. It is safe to call it multiple times.
788 * It returns 0 on success and -1 in error case.
789 */
790static int ssl_sock_init(struct connection *conn)
791{
792 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200793 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200794 return 0;
795
Willy Tarreau403edff2012-09-06 11:58:37 +0200796 if (global.maxsslconn && sslconns >= global.maxsslconn)
797 return -1;
798
Emeric Brun46591952012-05-18 15:47:34 +0200799 /* If it is in client mode initiate SSL session
800 in connect state otherwise accept state */
801 if (target_srv(&conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200802 /* Alloc a new SSL session ctx */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200803 conn->xprt_ctx = SSL_new(target_srv(&conn->target)->ssl_ctx.ctx);
804 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200805 return -1;
806
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200807 SSL_set_connect_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200808 if (target_srv(&conn->target)->ssl_ctx.reused_sess)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200809 SSL_set_session(conn->xprt_ctx, target_srv(&conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +0200810
811 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200812 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200813
814 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200815 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200816
817 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200818 return 0;
819 }
820 else if (target_client(&conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200821 /* Alloc a new SSL session ctx */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200822 conn->xprt_ctx = SSL_new(target_client(&conn->target)->bind_conf->default_ctx);
823 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200824 return -1;
825
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200826 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200827
828 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200829 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200830
Emeric Brune1f38db2012-09-03 20:36:47 +0200831 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200832 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +0200833
Emeric Brun46591952012-05-18 15:47:34 +0200834 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200835 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200836
837 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200838 return 0;
839 }
840 /* don't know how to handle such a target */
841 return -1;
842}
843
844
845/* This is the callback which is used when an SSL handshake is pending. It
846 * updates the FD status if it wants some polling before being called again.
847 * It returns 0 if it fails in a fatal way or needs to poll to go further,
848 * otherwise it returns non-zero and removes itself from the connection's
849 * flags (the bit is provided in <flag> by the caller).
850 */
851int ssl_sock_handshake(struct connection *conn, unsigned int flag)
852{
853 int ret;
854
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200855 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200856 goto out_error;
857
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200858 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200859 if (ret != 1) {
860 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200861 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +0200862
863 if (ret == SSL_ERROR_WANT_WRITE) {
864 /* SSL handshake needs to write, L4 connection may not be ready */
865 __conn_sock_stop_recv(conn);
866 __conn_sock_poll_send(conn);
867 return 0;
868 }
869 else if (ret == SSL_ERROR_WANT_READ) {
870 /* SSL handshake needs to read, L4 connection is ready */
871 if (conn->flags & CO_FL_WAIT_L4_CONN)
872 conn->flags &= ~CO_FL_WAIT_L4_CONN;
873 __conn_sock_stop_send(conn);
874 __conn_sock_poll_recv(conn);
875 return 0;
876 }
Willy Tarreau89230192012-09-28 20:22:13 +0200877 else if (ret == SSL_ERROR_SYSCALL) {
878 /* if errno is null, then connection was successfully established */
879 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
880 conn->flags &= ~CO_FL_WAIT_L4_CONN;
881 goto out_error;
882 }
Emeric Brun46591952012-05-18 15:47:34 +0200883 else {
884 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +0200885 /* Note: OpenSSL may leave unread bytes in the socket's
886 * buffer, causing an RST to be emitted upon close() on
887 * TCP sockets. We first try to drain possibly pending
888 * data to avoid this as much as possible.
889 */
890 ret = recv(conn->t.sock.fd, trash, trashlen, MSG_NOSIGNAL|MSG_DONTWAIT);
Emeric Brun46591952012-05-18 15:47:34 +0200891 goto out_error;
892 }
893 }
894
895 /* Handshake succeeded */
896 if (target_srv(&conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200897 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +0200898 /* check if session was reused, if not store current session on server for reuse */
899 if (target_srv(&conn->target)->ssl_ctx.reused_sess)
900 SSL_SESSION_free(target_srv(&conn->target)->ssl_ctx.reused_sess);
901
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200902 target_srv(&conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200903 }
904 }
905
906 /* The connection is now established at both layers, it's time to leave */
907 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
908 return 1;
909
910 out_error:
Emeric Brun9fa89732012-10-04 17:09:56 +0200911 /* free resumed session if exists */
912 if (target_srv(&conn->target) && target_srv(&conn->target)->ssl_ctx.reused_sess) {
913 SSL_SESSION_free(target_srv(&conn->target)->ssl_ctx.reused_sess);
914 target_srv(&conn->target)->ssl_ctx.reused_sess = NULL;
915 }
916
Emeric Brun46591952012-05-18 15:47:34 +0200917 /* Fail on all other handshake errors */
918 conn->flags |= CO_FL_ERROR;
919 conn->flags &= ~flag;
920 return 0;
921}
922
923/* Receive up to <count> bytes from connection <conn>'s socket and store them
924 * into buffer <buf>. The caller must ensure that <count> is always smaller
925 * than the buffer's size. Only one call to recv() is performed, unless the
926 * buffer wraps, in which case a second call may be performed. The connection's
927 * flags are updated with whatever special event is detected (error, read0,
928 * empty). The caller is responsible for taking care of those events and
929 * avoiding the call if inappropriate. The function does not call the
930 * connection's polling update function, so the caller is responsible for this.
931 */
932static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
933{
934 int ret, done = 0;
935 int try = count;
936
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200937 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200938 goto out_error;
939
940 if (conn->flags & CO_FL_HANDSHAKE)
941 /* a handshake was requested */
942 return 0;
943
944 /* compute the maximum block size we can read at once. */
945 if (buffer_empty(buf)) {
946 /* let's realign the buffer to optimize I/O */
947 buf->p = buf->data;
948 }
949 else if (buf->data + buf->o < buf->p &&
950 buf->p + buf->i < buf->data + buf->size) {
951 /* remaining space wraps at the end, with a moving limit */
952 if (try > buf->data + buf->size - (buf->p + buf->i))
953 try = buf->data + buf->size - (buf->p + buf->i);
954 }
955
956 /* read the largest possible block. For this, we perform only one call
957 * to recv() unless the buffer wraps and we exactly fill the first hunk,
958 * in which case we accept to do it once again. A new attempt is made on
959 * EINTR too.
960 */
961 while (try) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200962 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +0200963 if (conn->flags & CO_FL_ERROR) {
964 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
965 break;
966 }
Emeric Brun46591952012-05-18 15:47:34 +0200967 if (ret > 0) {
968 buf->i += ret;
969 done += ret;
970 if (ret < try)
971 break;
972 count -= ret;
973 try = count;
974 }
975 else if (ret == 0) {
976 goto read0;
977 }
978 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200979 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +0200980 if (ret == SSL_ERROR_WANT_WRITE) {
981 /* handshake is running, and it needs to poll for a write event */
982 conn->flags |= CO_FL_SSL_WAIT_HS;
983 __conn_sock_poll_send(conn);
984 break;
985 }
986 else if (ret == SSL_ERROR_WANT_READ) {
987 /* we need to poll for retry a read later */
988 __conn_data_poll_recv(conn);
989 break;
990 }
991 /* otherwise it's a real error */
992 goto out_error;
993 }
994 }
995 return done;
996
997 read0:
998 conn_sock_read0(conn);
999 return done;
1000 out_error:
1001 conn->flags |= CO_FL_ERROR;
1002 return done;
1003}
1004
1005
1006/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1007 * <flags> may contain MSG_MORE to make the system hold on without sending
1008 * data too fast, but this flag is ignored at the moment.
1009 * Only one call to send() is performed, unless the buffer wraps, in which case
1010 * a second call may be performed. The connection's flags are updated with
1011 * whatever special event is detected (error, empty). The caller is responsible
1012 * for taking care of those events and avoiding the call if inappropriate. The
1013 * function does not call the connection's polling update function, so the caller
1014 * is responsible for this.
1015 */
1016static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1017{
1018 int ret, try, done;
1019
1020 done = 0;
1021
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001022 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001023 goto out_error;
1024
1025 if (conn->flags & CO_FL_HANDSHAKE)
1026 /* a handshake was requested */
1027 return 0;
1028
1029 /* send the largest possible block. For this we perform only one call
1030 * to send() unless the buffer wraps and we exactly fill the first hunk,
1031 * in which case we accept to do it once again.
1032 */
1033 while (buf->o) {
1034 try = buf->o;
1035 /* outgoing data may wrap at the end */
1036 if (buf->data + try > buf->p)
1037 try = buf->data + try - buf->p;
1038
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001039 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001040 if (conn->flags & CO_FL_ERROR) {
1041 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
1042 break;
1043 }
Emeric Brun46591952012-05-18 15:47:34 +02001044 if (ret > 0) {
1045 buf->o -= ret;
1046 done += ret;
1047
1048 if (likely(!buffer_len(buf)))
1049 /* optimize data alignment in the buffer */
1050 buf->p = buf->data;
1051
1052 /* if the system buffer is full, don't insist */
1053 if (ret < try)
1054 break;
1055 }
1056 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001057 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001058 if (ret == SSL_ERROR_WANT_WRITE) {
1059 /* we need to poll to retry a write later */
1060 __conn_data_poll_send(conn);
1061 break;
1062 }
1063 else if (ret == SSL_ERROR_WANT_READ) {
1064 /* handshake is running, and
1065 it needs to poll for a read event,
1066 write polling must be disabled cause
1067 we are sure we can't write anything more
1068 before handshake re-performed */
1069 conn->flags |= CO_FL_SSL_WAIT_HS;
1070 __conn_sock_poll_recv(conn);
1071 break;
1072 }
1073 goto out_error;
1074 }
1075 }
1076 return done;
1077
1078 out_error:
1079 conn->flags |= CO_FL_ERROR;
1080 return done;
1081}
1082
1083
1084static void ssl_sock_close(struct connection *conn) {
1085
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001086 if (conn->xprt_ctx) {
1087 SSL_free(conn->xprt_ctx);
1088 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001089 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001090 }
Emeric Brun46591952012-05-18 15:47:34 +02001091}
1092
1093/* This function tries to perform a clean shutdown on an SSL connection, and in
1094 * any case, flags the connection as reusable if no handshake was in progress.
1095 */
1096static void ssl_sock_shutw(struct connection *conn, int clean)
1097{
1098 if (conn->flags & CO_FL_HANDSHAKE)
1099 return;
1100 /* no handshake was in progress, try a clean ssl shutdown */
1101 if (clean)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001102 SSL_shutdown(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001103
1104 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001105 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001106}
1107
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001108/* used for logging, may be changed for a sample fetch later */
1109const char *ssl_sock_get_cipher_name(struct connection *conn)
1110{
1111 if (!conn->xprt && !conn->xprt_ctx)
1112 return NULL;
1113 return SSL_get_cipher_name(conn->xprt_ctx);
1114}
1115
1116/* used for logging, may be changed for a sample fetch later */
1117const char *ssl_sock_get_proto_version(struct connection *conn)
1118{
1119 if (!conn->xprt && !conn->xprt_ctx)
1120 return NULL;
1121 return SSL_get_version(conn->xprt_ctx);
1122}
1123
Willy Tarreau8d598402012-10-22 17:58:39 +02001124/* Extract a serial from a cert, and copy it to a chunk.
1125 * Returns 1 if serial is found and copied, 0 if no serial found and
1126 * -1 if output is not large enough.
1127 */
1128static int
1129ssl_sock_get_serial(X509 *crt, struct chunk *out)
1130{
1131 ASN1_INTEGER *serial;
1132
1133 serial = X509_get_serialNumber(crt);
1134 if (!serial)
1135 return 0;
1136
1137 if (out->size < serial->length)
1138 return -1;
1139
1140 memcpy(out->str, serial->data, serial->length);
1141 out->len = serial->length;
1142 return 1;
1143}
1144
Emeric Brunce5ad802012-10-22 14:11:22 +02001145
1146/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1147 * Returns 1 if serial is found and copied, 0 if no valid time found
1148 * and -1 if output is not large enough.
1149 */
1150static int
1151ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1152{
1153 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1154 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1155
1156 if (gentm->length < 12)
1157 return 0;
1158 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1159 return 0;
1160 if (out->size < gentm->length-2)
1161 return -1;
1162
1163 memcpy(out->str, gentm->data+2, gentm->length-2);
1164 out->len = gentm->length-2;
1165 return 1;
1166 }
1167 else if (tm->type == V_ASN1_UTCTIME) {
1168 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1169
1170 if (utctm->length < 10)
1171 return 0;
1172 if (utctm->data[0] >= 0x35)
1173 return 0;
1174 if (out->size < utctm->length)
1175 return -1;
1176
1177 memcpy(out->str, utctm->data, utctm->length);
1178 out->len = utctm->length;
1179 return 1;
1180 }
1181
1182 return 0;
1183}
1184
Emeric Brun87855892012-10-17 17:39:35 +02001185/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1186 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1187 */
1188static int
1189ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1190{
1191 X509_NAME_ENTRY *ne;
1192 int i, j, n;
1193 int cur = 0;
1194 const char *s;
1195 char tmp[128];
1196
1197 out->len = 0;
1198 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1199 if (pos < 0)
1200 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1201 else
1202 j = i;
1203
1204 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1205 n = OBJ_obj2nid(ne->object);
1206 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1207 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1208 s = tmp;
1209 }
1210
1211 if (chunk_strcasecmp(entry, s) != 0)
1212 continue;
1213
1214 if (pos < 0)
1215 cur--;
1216 else
1217 cur++;
1218
1219 if (cur != pos)
1220 continue;
1221
1222 if (ne->value->length > out->size)
1223 return -1;
1224
1225 memcpy(out->str, ne->value->data, ne->value->length);
1226 out->len = ne->value->length;
1227 return 1;
1228 }
1229
1230 return 0;
1231
1232}
1233
1234/* Extract and format full DN from a X509_NAME and copy result into a chunk
1235 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1236 */
1237static int
1238ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1239{
1240 X509_NAME_ENTRY *ne;
1241 int i, n, ln;
1242 int l = 0;
1243 const char *s;
1244 char *p;
1245 char tmp[128];
1246
1247 out->len = 0;
1248 p = out->str;
1249 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1250 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1251 n = OBJ_obj2nid(ne->object);
1252 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1253 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1254 s = tmp;
1255 }
1256 ln = strlen(s);
1257
1258 l += 1 + ln + 1 + ne->value->length;
1259 if (l > out->size)
1260 return -1;
1261 out->len = l;
1262
1263 *(p++)='/';
1264 memcpy(p, s, ln);
1265 p += ln;
1266 *(p++)='=';
1267 memcpy(p, ne->value->data, ne->value->length);
1268 p += ne->value->length;
1269 }
1270
1271 if (!out->len)
1272 return 0;
1273
1274 return 1;
1275}
1276
Willy Tarreau7875d092012-09-10 08:20:03 +02001277/***** Below are some sample fetching functions for ACL/patterns *****/
1278
Emeric Brune64aef12012-09-21 13:15:06 +02001279/* boolean, returns true if client cert was present */
1280static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001281smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1282 const struct arg *args, struct sample *smp)
Emeric Brune64aef12012-09-21 13:15:06 +02001283{
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001284 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001285 return 0;
1286
1287 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1288 smp->flags |= SMP_F_MAY_CHANGE;
1289 return 0;
1290 }
1291
1292 smp->flags = 0;
1293 smp->type = SMP_T_BOOL;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001294 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn.xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001295
1296 return 1;
1297}
1298
Willy Tarreau8d598402012-10-22 17:58:39 +02001299/* bin, returns serial in a binary chunk */
1300static int
1301smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1302 const struct arg *args, struct sample *smp)
1303{
1304 X509 *crt = NULL;
1305 int ret = 0;
1306 struct chunk *smp_trash;
1307
1308 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1309 return 0;
1310
1311 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1312 smp->flags |= SMP_F_MAY_CHANGE;
1313 return 0;
1314 }
1315
1316 /* SSL_get_peer_certificate, it increase X509 * ref count */
1317 crt = SSL_get_peer_certificate(l4->si[0].conn.xprt_ctx);
1318 if (!crt)
1319 goto out;
1320
1321 smp_trash = sample_get_trash_chunk();
1322 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1323 goto out;
1324
1325 smp->data.str = *smp_trash;
1326 smp->type = SMP_T_BIN;
1327 ret = 1;
1328out:
1329 if (crt)
1330 X509_free(crt);
1331 return ret;
1332}
Emeric Brune64aef12012-09-21 13:15:06 +02001333
Emeric Brunce5ad802012-10-22 14:11:22 +02001334/*str, returns notafter date in ASN1_UTCTIME format */
1335static int
1336smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1337 const struct arg *args, struct sample *smp)
1338{
1339 X509 *crt = NULL;
1340 int ret = 0;
1341 struct chunk *smp_trash;
1342
1343 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1344 return 0;
1345
1346 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1347 smp->flags |= SMP_F_MAY_CHANGE;
1348 return 0;
1349 }
1350
1351 /* SSL_get_peer_certificate, it increase X509 * ref count */
1352 crt = SSL_get_peer_certificate(l4->si[0].conn.xprt_ctx);
1353 if (!crt)
1354 goto out;
1355
1356 smp_trash = sample_get_trash_chunk();
1357 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1358 goto out;
1359
1360 smp->data.str = *smp_trash;
1361 smp->type = SMP_T_STR;
1362 ret = 1;
1363out:
1364 if (crt)
1365 X509_free(crt);
1366 return ret;
1367}
1368
Emeric Brun87855892012-10-17 17:39:35 +02001369/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1370static int
1371smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1372 const struct arg *args, struct sample *smp)
1373{
1374 X509 *crt = NULL;
1375 X509_NAME *name;
1376 int ret = 0;
1377 struct chunk *smp_trash;
1378
1379 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1380 return 0;
1381
1382 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1383 smp->flags |= SMP_F_MAY_CHANGE;
1384 return 0;
1385 }
1386
1387 /* SSL_get_peer_certificate, it increase X509 * ref count */
1388 crt = SSL_get_peer_certificate(l4->si[0].conn.xprt_ctx);
1389 if (!crt)
1390 goto out;
1391
1392 name = X509_get_issuer_name(crt);
1393 if (!name)
1394 goto out;
1395
1396 smp_trash = sample_get_trash_chunk();
1397 if (args && args[0].type == ARGT_STR) {
1398 int pos = 1;
1399
1400 if (args[1].type == ARGT_SINT)
1401 pos = args[1].data.sint;
1402 else if (args[1].type == ARGT_UINT)
1403 pos =(int)args[1].data.uint;
1404
1405 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1406 goto out;
1407 }
1408 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1409 goto out;
1410
1411 smp->type = SMP_T_STR;
1412 smp->data.str = *smp_trash;
1413 ret = 1;
1414out:
1415 if (crt)
1416 X509_free(crt);
1417 return ret;
1418}
1419
Emeric Brunce5ad802012-10-22 14:11:22 +02001420/*str, returns notbefore date in ASN1_UTCTIME format */
1421static int
1422smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1423 const struct arg *args, struct sample *smp)
1424{
1425 X509 *crt = NULL;
1426 int ret = 0;
1427 struct chunk *smp_trash;
1428
1429 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1430 return 0;
1431
1432 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1433 smp->flags |= SMP_F_MAY_CHANGE;
1434 return 0;
1435 }
1436
1437 /* SSL_get_peer_certificate, it increase X509 * ref count */
1438 crt = SSL_get_peer_certificate(l4->si[0].conn.xprt_ctx);
1439 if (!crt)
1440 goto out;
1441
1442 smp_trash = sample_get_trash_chunk();
1443 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1444 goto out;
1445
1446 smp->data.str = *smp_trash;
1447 smp->type = SMP_T_STR;
1448 ret = 1;
1449out:
1450 if (crt)
1451 X509_free(crt);
1452 return ret;
1453}
1454
Emeric Brun87855892012-10-17 17:39:35 +02001455/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1456static int
1457smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1458 const struct arg *args, struct sample *smp)
1459{
1460 X509 *crt = NULL;
1461 X509_NAME *name;
1462 int ret = 0;
1463 struct chunk *smp_trash;
1464
1465 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1466 return 0;
1467
1468 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1469 smp->flags |= SMP_F_MAY_CHANGE;
1470 return 0;
1471 }
1472
1473 /* SSL_get_peer_certificate, it increase X509 * ref count */
1474 crt = SSL_get_peer_certificate(l4->si[0].conn.xprt_ctx);
1475 if (!crt)
1476 goto out;
1477
1478 name = X509_get_subject_name(crt);
1479 if (!name)
1480 goto out;
1481
1482 smp_trash = sample_get_trash_chunk();
1483 if (args && args[0].type == ARGT_STR) {
1484 int pos = 1;
1485
1486 if (args[1].type == ARGT_SINT)
1487 pos = args[1].data.sint;
1488 else if (args[1].type == ARGT_UINT)
1489 pos =(int)args[1].data.uint;
1490
1491 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1492 goto out;
1493 }
1494 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1495 goto out;
1496
1497 smp->type = SMP_T_STR;
1498 smp->data.str = *smp_trash;
1499 ret = 1;
1500out:
1501 if (crt)
1502 X509_free(crt);
1503 return ret;
1504}
Emeric Bruna7359fd2012-10-17 15:03:11 +02001505/* integer, returns the client certificate version */
1506static int
1507smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1508 const struct arg *args, struct sample *smp)
1509{
1510 X509 *crt;
1511
1512 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1513 return 0;
1514
1515 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1516 smp->flags |= SMP_F_MAY_CHANGE;
1517 return 0;
1518 }
1519
1520 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
1521 crt = SSL_get_peer_certificate(l4->si[0].conn.xprt_ctx);
1522 if (!crt)
1523 return 0;
1524
1525 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1526 X509_free(crt);
1527 smp->type = SMP_T_UINT;
1528
1529 return 1;
1530}
1531
Emeric Brun7f56e742012-10-19 18:15:40 +02001532/* str, returns the client certificate sig alg */
1533static int
1534smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1535 const struct arg *args, struct sample *smp)
1536{
1537 X509 *crt;
1538 int nid;
1539
1540 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1541 return 0;
1542
1543 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1544 smp->flags |= SMP_F_MAY_CHANGE;
1545 return 0;
1546 }
1547
1548 /* SSL_get_peer_certificate increase X509 * ref count */
1549 crt = SSL_get_peer_certificate(l4->si[0].conn.xprt_ctx);
1550 if (!crt)
1551 return 0;
1552
1553 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1554
1555 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1556 if (!smp->data.str.str)
1557 return 0;
1558
1559 smp->type = SMP_T_CSTR;
1560 smp->data.str.len = strlen(smp->data.str.str);
1561 X509_free(crt);
1562
1563 return 1;
1564}
1565
Emeric Brun521a0112012-10-22 12:22:55 +02001566/* str, returns the client certificate key alg */
1567static int
1568smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1569 const struct arg *args, struct sample *smp)
1570{
1571 X509 *crt;
1572 int nid;
1573
1574 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1575 return 0;
1576
1577 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1578 smp->flags |= SMP_F_MAY_CHANGE;
1579 return 0;
1580 }
1581
1582 /* SSL_get_peer_certificate increase X509 * ref count */
1583 crt = SSL_get_peer_certificate(l4->si[0].conn.xprt_ctx);
1584 if (!crt)
1585 return 0;
1586
1587 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1588
1589 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1590 if (!smp->data.str.str)
1591 return 0;
1592
1593 smp->type = SMP_T_CSTR;
1594 smp->data.str.len = strlen(smp->data.str.str);
1595 X509_free(crt);
1596
1597 return 1;
1598}
1599
Emeric Brun2525b6b2012-10-18 15:59:43 +02001600/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02001601static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001602smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau7875d092012-09-10 08:20:03 +02001603 const struct arg *args, struct sample *smp)
1604{
1605 smp->type = SMP_T_BOOL;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001606 smp->data.uint = (l4->si[0].conn.xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02001607 return 1;
1608}
1609
Emeric Brun2525b6b2012-10-18 15:59:43 +02001610/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02001611static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001612smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1613 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02001614{
1615#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1616 smp->type = SMP_T_BOOL;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001617 smp->data.uint = (l4->si[0].conn.xprt == &ssl_sock) &&
1618 l4->si[0].conn.xprt_ctx &&
1619 SSL_get_servername(l4->si[0].conn.xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02001620 return 1;
1621#else
1622 return 0;
1623#endif
1624}
1625
Willy Tarreau8d598402012-10-22 17:58:39 +02001626/* bin, returns serial in a binary chunk */
1627static int
1628smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1629 const struct arg *args, struct sample *smp)
1630{
1631 X509 *crt = NULL;
1632 int ret = 0;
1633 struct chunk *smp_trash;
1634
1635 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1636 return 0;
1637
1638 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1639 smp->flags |= SMP_F_MAY_CHANGE;
1640 return 0;
1641 }
1642
1643 crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
1644 if (!crt)
1645 goto out;
1646
1647 smp_trash = sample_get_trash_chunk();
1648 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1649 goto out;
1650
1651 smp->data.str = *smp_trash;
1652 smp->type = SMP_T_BIN;
1653 ret = 1;
1654out:
1655 return ret;
1656}
Emeric Brunce5ad802012-10-22 14:11:22 +02001657/*str, returns notafter date in ASN1_UTCTIME format */
1658static int
1659smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1660 const struct arg *args, struct sample *smp)
1661{
1662 X509 *crt = NULL;
1663 int ret = 0;
1664 struct chunk *smp_trash;
1665
1666 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1667 return 0;
1668
1669 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1670 smp->flags |= SMP_F_MAY_CHANGE;
1671 return 0;
1672 }
1673
1674 crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
1675 if (!crt)
1676 goto out;
1677
1678 smp_trash = sample_get_trash_chunk();
1679 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1680 goto out;
1681
1682 smp->data.str = *smp_trash;
1683 smp->type = SMP_T_STR;
1684 ret = 1;
1685out:
1686 return ret;
1687}
1688
1689/*str, returns notbefore date in ASN1_UTCTIME format */
1690static int
1691smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1692 const struct arg *args, struct sample *smp)
1693{
1694 X509 *crt = NULL;
1695 int ret = 0;
1696 struct chunk *smp_trash;
1697
1698 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1699 return 0;
1700
1701 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1702 smp->flags |= SMP_F_MAY_CHANGE;
1703 return 0;
1704 }
1705
1706 crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
1707 if (!crt)
1708 goto out;
1709
1710 smp_trash = sample_get_trash_chunk();
1711 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1712 goto out;
1713
1714 smp->data.str = *smp_trash;
1715 smp->type = SMP_T_STR;
1716 ret = 1;
1717out:
1718 return ret;
1719}
Willy Tarreau8d598402012-10-22 17:58:39 +02001720
Emeric Bruna7359fd2012-10-17 15:03:11 +02001721/* integer, returns the frontend certificate version */
1722static int
1723smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1724 const struct arg *args, struct sample *smp)
1725{
1726 X509 *crt;
1727
1728 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1729 return 0;
1730
1731 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1732 smp->flags |= SMP_F_MAY_CHANGE;
1733 return 0;
1734 }
1735
1736 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
1737 crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
1738 if (!crt)
1739 return 0;
1740
1741 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1742 smp->type = SMP_T_UINT;
1743
1744 return 1;
1745}
1746
Emeric Brun7f56e742012-10-19 18:15:40 +02001747/* str, returns the client certificate sig alg */
1748static int
1749smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1750 const struct arg *args, struct sample *smp)
1751{
1752 X509 *crt;
1753 int nid;
1754
1755 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1756 return 0;
1757
1758 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1759 smp->flags |= SMP_F_MAY_CHANGE;
1760 return 0;
1761 }
1762
1763 crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
1764 if (!crt)
1765 return 0;
1766
1767 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1768
1769 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1770 if (!smp->data.str.str)
1771 return 0;
1772
1773 smp->type = SMP_T_CSTR;
1774 smp->data.str.len = strlen(smp->data.str.str);
1775
1776 return 1;
1777}
1778
Emeric Brun521a0112012-10-22 12:22:55 +02001779/* str, returns the client certificate key alg */
1780static int
1781smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1782 const struct arg *args, struct sample *smp)
1783{
1784 X509 *crt;
1785 int nid;
1786
1787 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1788 return 0;
1789
1790 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1791 smp->flags |= SMP_F_MAY_CHANGE;
1792 return 0;
1793 }
1794
1795 crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
1796 if (!crt)
1797 return 0;
1798
1799 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1800
1801 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1802 if (!smp->data.str.str)
1803 return 0;
1804
1805 smp->type = SMP_T_CSTR;
1806 smp->data.str.len = strlen(smp->data.str.str);
1807
1808 return 1;
1809}
1810
Emeric Brun87855892012-10-17 17:39:35 +02001811/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1812static int
1813smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1814 const struct arg *args, struct sample *smp)
1815{
1816 X509 *crt = NULL;
1817 X509_NAME *name;
1818 int ret = 0;
1819 struct chunk *smp_trash;
1820
1821 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1822 return 0;
1823
1824 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1825 smp->flags |= SMP_F_MAY_CHANGE;
1826 return 0;
1827 }
1828
1829 crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
1830 if (!crt)
1831 goto out;
1832
1833 name = X509_get_issuer_name(crt);
1834 if (!name)
1835 goto out;
1836
1837 smp_trash = sample_get_trash_chunk();
1838 if (args && args[0].type == ARGT_STR) {
1839 int pos = 1;
1840
1841 if (args[1].type == ARGT_SINT)
1842 pos = args[1].data.sint;
1843 else if (args[1].type == ARGT_UINT)
1844 pos =(int)args[1].data.uint;
1845
1846 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1847 goto out;
1848 }
1849 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1850 goto out;
1851
1852 smp->type = SMP_T_STR;
1853 smp->data.str = *smp_trash;
1854 ret = 1;
1855out:
1856 return ret;
1857}
1858
1859/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1860static int
1861smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1862 const struct arg *args, struct sample *smp)
1863{
1864 X509 *crt = NULL;
1865 X509_NAME *name;
1866 int ret = 0;
1867 struct chunk *smp_trash;
1868
1869 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1870 return 0;
1871
1872 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1873 smp->flags |= SMP_F_MAY_CHANGE;
1874 return 0;
1875 }
1876
1877 crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
1878 if (!crt)
1879 goto out;
1880
1881 name = X509_get_subject_name(crt);
1882 if (!name)
1883 goto out;
1884
1885 smp_trash = sample_get_trash_chunk();
1886 if (args && args[0].type == ARGT_STR) {
1887 int pos = 1;
1888
1889 if (args[1].type == ARGT_SINT)
1890 pos = args[1].data.sint;
1891 else if (args[1].type == ARGT_UINT)
1892 pos =(int)args[1].data.uint;
1893
1894 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1895 goto out;
1896 }
1897 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1898 goto out;
1899
1900 smp->type = SMP_T_STR;
1901 smp->data.str = *smp_trash;
1902 ret = 1;
1903out:
1904 return ret;
1905}
1906
Emeric Brun589fcad2012-10-16 14:13:26 +02001907static int
1908smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1909 const struct arg *args, struct sample *smp)
1910{
1911 smp->flags = 0;
1912
1913 if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
1914 return 0;
1915
1916 smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn.xprt_ctx);
1917 if (!smp->data.str.str)
1918 return 0;
1919
1920 smp->type = SMP_T_CSTR;
1921 smp->data.str.len = strlen(smp->data.str.str);
1922
1923 return 1;
1924}
1925
1926static int
1927smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1928 const struct arg *args, struct sample *smp)
1929{
1930 smp->flags = 0;
1931
1932 if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
1933 return 0;
1934
1935 if (!SSL_get_cipher_bits(l4->si[0].conn.xprt_ctx, (int *)&smp->data.uint))
1936 return 0;
1937
1938 smp->type = SMP_T_UINT;
1939
1940 return 1;
1941}
1942
1943static int
1944smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1945 const struct arg *args, struct sample *smp)
1946{
1947 smp->flags = 0;
1948
1949 if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
1950 return 0;
1951
1952 smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn.xprt_ctx, NULL);
1953 if (!smp->data.uint)
1954 return 0;
1955
1956 smp->type = SMP_T_UINT;
1957
1958 return 1;
1959}
1960
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001961#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02001962static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001963smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1964 const struct arg *args, struct sample *smp)
Willy Tarreaua33c6542012-10-15 13:19:06 +02001965{
Willy Tarreaua33c6542012-10-15 13:19:06 +02001966 smp->flags = 0;
1967 smp->type = SMP_T_CSTR;
1968
1969 if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
1970 return 0;
1971
1972 smp->data.str.str = NULL;
1973 SSL_get0_next_proto_negotiated(l4->si[0].conn.xprt_ctx,
1974 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
1975
1976 if (!smp->data.str.str)
1977 return 0;
1978
1979 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02001980}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001981#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02001982
1983static int
Emeric Brun589fcad2012-10-16 14:13:26 +02001984smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1985 const struct arg *args, struct sample *smp)
1986{
1987 smp->flags = 0;
1988
1989 if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
1990 return 0;
1991
1992 smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn.xprt_ctx);
1993 if (!smp->data.str.str)
1994 return 0;
1995
1996 smp->type = SMP_T_CSTR;
1997 smp->data.str.len = strlen(smp->data.str.str);
1998
1999 return 1;
2000}
2001
2002static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002003smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2004 const struct arg *args, struct sample *smp)
2005{
2006#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2007 SSL_SESSION *sess;
2008
2009 smp->flags = 0;
2010 smp->type = SMP_T_CBIN;
2011
2012 if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
2013 return 0;
2014
2015 sess = SSL_get_session(l4->si[0].conn.xprt_ctx);
2016 if (!sess)
2017 return 0;
2018
2019 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2020 if (!smp->data.str.str || !&smp->data.str.len)
2021 return 0;
2022
2023 return 1;
2024#else
2025 return 0;
2026#endif
2027}
2028
2029static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002030smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2031 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02002032{
2033#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2034 smp->flags = 0;
2035 smp->type = SMP_T_CSTR;
2036
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002037 if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
Willy Tarreau7875d092012-09-10 08:20:03 +02002038 return 0;
2039
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002040 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 +02002041 if (!smp->data.str.str)
2042 return 0;
2043
Willy Tarreau7875d092012-09-10 08:20:03 +02002044 smp->data.str.len = strlen(smp->data.str.str);
2045 return 1;
2046#else
2047 return 0;
2048#endif
2049}
2050
Emeric Brun2525b6b2012-10-18 15:59:43 +02002051/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002052static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002053smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002054 const struct arg *args, struct sample *smp)
2055{
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002056 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002057 return 0;
2058
2059 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
2060 smp->flags = SMP_F_MAY_CHANGE;
2061 return 0;
2062 }
2063
2064 smp->type = SMP_T_UINT;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002065 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn.xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002066 smp->flags = 0;
2067
2068 return 1;
2069}
2070
Emeric Brun2525b6b2012-10-18 15:59:43 +02002071/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002072static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002073smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002074 const struct arg *args, struct sample *smp)
2075{
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002076 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002077 return 0;
2078
2079 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
2080 smp->flags = SMP_F_MAY_CHANGE;
2081 return 0;
2082 }
2083
2084 smp->type = SMP_T_UINT;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002085 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn.xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002086 smp->flags = 0;
2087
2088 return 1;
2089}
2090
Emeric Brun2525b6b2012-10-18 15:59:43 +02002091/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002092static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002093smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2094 const struct arg *args, struct sample *smp)
Emeric Brunf282a812012-09-21 15:27:54 +02002095{
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002096 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002097 return 0;
2098
2099 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
2100 smp->flags = SMP_F_MAY_CHANGE;
2101 return 0;
2102 }
2103
2104 smp->type = SMP_T_UINT;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002105 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn.xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002106 smp->flags = 0;
2107
2108 return 1;
2109}
2110
Emeric Brun2525b6b2012-10-18 15:59:43 +02002111/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002112static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002113smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2114 const struct arg *args, struct sample *smp)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002115{
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002116 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002117 return 0;
2118
2119 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
2120 smp->flags = SMP_F_MAY_CHANGE;
2121 return 0;
2122 }
2123
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002124 if (!l4->si[0].conn.xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002125 return 0;
2126
2127 smp->type = SMP_T_UINT;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002128 smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn.xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002129 smp->flags = 0;
2130
2131 return 1;
2132}
2133
Emeric Brunfb510ea2012-10-05 12:00:26 +02002134/* parse the "ca-file" bind keyword */
2135static 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 +02002136{
2137 if (!*args[cur_arg + 1]) {
2138 if (err)
2139 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2140 return ERR_ALERT | ERR_FATAL;
2141 }
2142
Emeric Brunef42d922012-10-11 16:11:36 +02002143 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2144 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2145 else
2146 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002147
Emeric Brund94b3fe2012-09-20 18:23:56 +02002148 return 0;
2149}
2150
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002151/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002152static 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 +02002153{
2154 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002155 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002156 return ERR_ALERT | ERR_FATAL;
2157 }
2158
Emeric Brun76d88952012-10-05 15:47:31 +02002159 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002160 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002161 return 0;
2162}
2163
2164/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002165static 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 +02002166{
Emeric Brunc8e8d122012-10-02 18:42:10 +02002167 char path[PATH_MAX];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002168 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002169 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002170 return ERR_ALERT | ERR_FATAL;
2171 }
2172
Emeric Brunc8e8d122012-10-02 18:42:10 +02002173 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
2174 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > PATH_MAX) {
2175 memprintf(err, "'%s' : path too long", args[cur_arg]);
2176 return ERR_ALERT | ERR_FATAL;
2177 }
2178 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2179 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2180 return ERR_ALERT | ERR_FATAL;
2181
2182 return 0;
2183 }
2184
Willy Tarreau4348fad2012-09-20 16:48:07 +02002185 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002186 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002187
2188 return 0;
2189}
2190
Emeric Brunfb510ea2012-10-05 12:00:26 +02002191/* parse the "crl-file" bind keyword */
2192static 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 +02002193{
Emeric Brun051cdab2012-10-02 19:25:50 +02002194#ifndef X509_V_FLAG_CRL_CHECK
2195 if (err)
2196 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2197 return ERR_ALERT | ERR_FATAL;
2198#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002199 if (!*args[cur_arg + 1]) {
2200 if (err)
2201 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2202 return ERR_ALERT | ERR_FATAL;
2203 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002204
Emeric Brunef42d922012-10-11 16:11:36 +02002205 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2206 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2207 else
2208 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002209
Emeric Brun2b58d042012-09-20 17:10:03 +02002210 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002211#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002212}
2213
2214/* parse the "ecdhe" bind keyword keywords */
2215static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2216{
2217#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2218 if (err)
2219 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2220 return ERR_ALERT | ERR_FATAL;
2221#elif defined(OPENSSL_NO_ECDH)
2222 if (err)
2223 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2224 return ERR_ALERT | ERR_FATAL;
2225#else
2226 if (!*args[cur_arg + 1]) {
2227 if (err)
2228 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2229 return ERR_ALERT | ERR_FATAL;
2230 }
2231
2232 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002233
2234 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002235#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002236}
2237
Emeric Brun81c00f02012-09-21 14:31:21 +02002238/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2239static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2240{
2241 int code;
2242 char *p = args[cur_arg + 1];
2243 unsigned long long *ignerr = &conf->crt_ignerr;
2244
2245 if (!*p) {
2246 if (err)
2247 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2248 return ERR_ALERT | ERR_FATAL;
2249 }
2250
2251 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2252 ignerr = &conf->ca_ignerr;
2253
2254 if (strcmp(p, "all") == 0) {
2255 *ignerr = ~0ULL;
2256 return 0;
2257 }
2258
2259 while (p) {
2260 code = atoi(p);
2261 if ((code <= 0) || (code > 63)) {
2262 if (err)
2263 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2264 args[cur_arg], code, args[cur_arg + 1]);
2265 return ERR_ALERT | ERR_FATAL;
2266 }
2267 *ignerr |= 1ULL << code;
2268 p = strchr(p, ',');
2269 if (p)
2270 p++;
2271 }
2272
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002273 return 0;
2274}
2275
2276/* parse the "force-sslv3" bind keyword */
2277static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2278{
2279 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2280 return 0;
2281}
2282
2283/* parse the "force-tlsv10" bind keyword */
2284static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2285{
2286 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002287 return 0;
2288}
2289
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002290/* parse the "force-tlsv11" bind keyword */
2291static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2292{
2293#if SSL_OP_NO_TLSv1_1
2294 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
2295 return 0;
2296#else
2297 if (err)
2298 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
2299 return ERR_ALERT | ERR_FATAL;
2300#endif
2301}
2302
2303/* parse the "force-tlsv12" bind keyword */
2304static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2305{
2306#if SSL_OP_NO_TLSv1_2
2307 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
2308 return 0;
2309#else
2310 if (err)
2311 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
2312 return ERR_ALERT | ERR_FATAL;
2313#endif
2314}
2315
2316
Emeric Brun2d0c4822012-10-02 13:45:20 +02002317/* parse the "no-tls-tickets" bind keyword */
2318static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2319{
Emeric Brun89675492012-10-05 13:48:26 +02002320 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02002321 return 0;
2322}
2323
Emeric Brun2d0c4822012-10-02 13:45:20 +02002324
Emeric Brun9b3009b2012-10-05 11:55:06 +02002325/* parse the "no-sslv3" bind keyword */
2326static 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 +02002327{
Emeric Brun89675492012-10-05 13:48:26 +02002328 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002329 return 0;
2330}
2331
Emeric Brun9b3009b2012-10-05 11:55:06 +02002332/* parse the "no-tlsv10" bind keyword */
2333static 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 +02002334{
Emeric Brun89675492012-10-05 13:48:26 +02002335 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002336 return 0;
2337}
2338
Emeric Brun9b3009b2012-10-05 11:55:06 +02002339/* parse the "no-tlsv11" bind keyword */
2340static 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 +02002341{
Emeric Brun89675492012-10-05 13:48:26 +02002342 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002343 return 0;
2344}
2345
Emeric Brun9b3009b2012-10-05 11:55:06 +02002346/* parse the "no-tlsv12" bind keyword */
2347static 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 +02002348{
Emeric Brun89675492012-10-05 13:48:26 +02002349 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002350 return 0;
2351}
2352
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002353/* parse the "npn" bind keyword */
2354static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2355{
2356#ifdef OPENSSL_NPN_NEGOTIATED
2357 char *p1, *p2;
2358
2359 if (!*args[cur_arg + 1]) {
2360 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
2361 return ERR_ALERT | ERR_FATAL;
2362 }
2363
2364 free(conf->npn_str);
2365
2366 /* the NPN string is built as a suite of (<len> <name>)* */
2367 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
2368 conf->npn_str = calloc(1, conf->npn_len);
2369 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
2370
2371 /* replace commas with the name length */
2372 p1 = conf->npn_str;
2373 p2 = p1 + 1;
2374 while (1) {
2375 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
2376 if (!p2)
2377 p2 = p1 + 1 + strlen(p1 + 1);
2378
2379 if (p2 - (p1 + 1) > 255) {
2380 *p2 = '\0';
2381 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2382 return ERR_ALERT | ERR_FATAL;
2383 }
2384
2385 *p1 = p2 - (p1 + 1);
2386 p1 = p2;
2387
2388 if (!*p2)
2389 break;
2390
2391 *(p2++) = '\0';
2392 }
2393 return 0;
2394#else
2395 if (err)
2396 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
2397 return ERR_ALERT | ERR_FATAL;
2398#endif
2399}
2400
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002401/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002402static 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 +02002403{
Willy Tarreau81796be2012-09-22 19:11:47 +02002404 struct listener *l;
2405
Willy Tarreau4348fad2012-09-20 16:48:07 +02002406 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02002407
2408 if (global.listen_default_ciphers && !conf->ciphers)
2409 conf->ciphers = strdup(global.listen_default_ciphers);
2410
Willy Tarreau81796be2012-09-22 19:11:47 +02002411 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002412 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02002413
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002414 return 0;
2415}
2416
Emeric Brund94b3fe2012-09-20 18:23:56 +02002417/* parse the "verify" bind keyword */
2418static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2419{
2420 if (!*args[cur_arg + 1]) {
2421 if (err)
2422 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
2423 return ERR_ALERT | ERR_FATAL;
2424 }
2425
2426 if (strcmp(args[cur_arg + 1], "none") == 0)
2427 conf->verify = SSL_VERIFY_NONE;
2428 else if (strcmp(args[cur_arg + 1], "optional") == 0)
2429 conf->verify = SSL_VERIFY_PEER;
2430 else if (strcmp(args[cur_arg + 1], "required") == 0)
2431 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2432 else {
2433 if (err)
2434 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
2435 args[cur_arg], args[cur_arg + 1]);
2436 return ERR_ALERT | ERR_FATAL;
2437 }
2438
2439 return 0;
2440}
2441
Willy Tarreau92faadf2012-10-10 23:04:25 +02002442/************** "server" keywords ****************/
2443
Emeric Brunef42d922012-10-11 16:11:36 +02002444/* parse the "ca-file" server keyword */
2445static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2446{
2447 if (!*args[*cur_arg + 1]) {
2448 if (err)
2449 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
2450 return ERR_ALERT | ERR_FATAL;
2451 }
2452
2453 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2454 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2455 else
2456 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
2457
2458 return 0;
2459}
2460
Willy Tarreau92faadf2012-10-10 23:04:25 +02002461/* parse the "check-ssl" server keyword */
2462static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2463{
2464 newsrv->check.use_ssl = 1;
2465 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2466 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2467 return 0;
2468}
2469
2470/* parse the "ciphers" server keyword */
2471static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2472{
2473 if (!*args[*cur_arg + 1]) {
2474 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
2475 return ERR_ALERT | ERR_FATAL;
2476 }
2477
2478 free(newsrv->ssl_ctx.ciphers);
2479 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
2480 return 0;
2481}
2482
Emeric Brunef42d922012-10-11 16:11:36 +02002483/* parse the "crl-file" server keyword */
2484static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2485{
2486#ifndef X509_V_FLAG_CRL_CHECK
2487 if (err)
2488 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
2489 return ERR_ALERT | ERR_FATAL;
2490#else
2491 if (!*args[*cur_arg + 1]) {
2492 if (err)
2493 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
2494 return ERR_ALERT | ERR_FATAL;
2495 }
2496
2497 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2498 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2499 else
2500 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
2501
2502 return 0;
2503#endif
2504}
2505
Emeric Bruna7aa3092012-10-26 12:58:00 +02002506/* parse the "crt" server keyword */
2507static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2508{
2509 if (!*args[*cur_arg + 1]) {
2510 if (err)
2511 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
2512 return ERR_ALERT | ERR_FATAL;
2513 }
2514
2515 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
2516 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2517 else
2518 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
2519
2520 return 0;
2521}
Emeric Brunef42d922012-10-11 16:11:36 +02002522
Willy Tarreau92faadf2012-10-10 23:04:25 +02002523/* parse the "force-sslv3" server keyword */
2524static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2525{
2526 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
2527 return 0;
2528}
2529
2530/* parse the "force-tlsv10" server keyword */
2531static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2532{
2533 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
2534 return 0;
2535}
2536
2537/* parse the "force-tlsv11" server keyword */
2538static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2539{
2540#if SSL_OP_NO_TLSv1_1
2541 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
2542 return 0;
2543#else
2544 if (err)
2545 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
2546 return ERR_ALERT | ERR_FATAL;
2547#endif
2548}
2549
2550/* parse the "force-tlsv12" server keyword */
2551static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2552{
2553#if SSL_OP_NO_TLSv1_2
2554 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
2555 return 0;
2556#else
2557 if (err)
2558 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
2559 return ERR_ALERT | ERR_FATAL;
2560#endif
2561}
2562
2563/* parse the "no-sslv3" server keyword */
2564static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2565{
2566 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
2567 return 0;
2568}
2569
2570/* parse the "no-tlsv10" server keyword */
2571static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2572{
2573 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
2574 return 0;
2575}
2576
2577/* parse the "no-tlsv11" server keyword */
2578static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2579{
2580 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
2581 return 0;
2582}
2583
2584/* parse the "no-tlsv12" server keyword */
2585static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2586{
2587 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
2588 return 0;
2589}
2590
Emeric Brunf9c5c472012-10-11 15:28:34 +02002591/* parse the "no-tls-tickets" server keyword */
2592static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2593{
2594 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
2595 return 0;
2596}
2597
Willy Tarreau92faadf2012-10-10 23:04:25 +02002598/* parse the "ssl" server keyword */
2599static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2600{
2601 newsrv->use_ssl = 1;
2602 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2603 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2604 return 0;
2605}
2606
Emeric Brunef42d922012-10-11 16:11:36 +02002607/* parse the "verify" server keyword */
2608static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2609{
2610 if (!*args[*cur_arg + 1]) {
2611 if (err)
2612 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
2613 return ERR_ALERT | ERR_FATAL;
2614 }
2615
2616 if (strcmp(args[*cur_arg + 1], "none") == 0)
2617 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
2618 else if (strcmp(args[*cur_arg + 1], "required") == 0)
2619 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
2620 else {
2621 if (err)
2622 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
2623 args[*cur_arg], args[*cur_arg + 1]);
2624 return ERR_ALERT | ERR_FATAL;
2625 }
2626
2627 return 0;
2628}
2629
Willy Tarreau7875d092012-09-10 08:20:03 +02002630/* Note: must not be declared <const> as its list will be overwritten.
2631 * Please take care of keeping this list alphabetically sorted.
2632 */
2633static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
Emeric Brun2525b6b2012-10-18 15:59:43 +02002634 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2635 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2636 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun87855892012-10-17 17:39:35 +02002637 { "ssl_c_i_dn", smp_fetch_ssl_c_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun521a0112012-10-22 12:22:55 +02002638 { "ssl_c_key_alg", smp_fetch_ssl_c_key_alg, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brunce5ad802012-10-22 14:11:22 +02002639 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
2640 { "ssl_c_notbefore", smp_fetch_ssl_c_notbefore, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun7f56e742012-10-19 18:15:40 +02002641 { "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun87855892012-10-17 17:39:35 +02002642 { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Willy Tarreau8d598402012-10-22 17:58:39 +02002643 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002644 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Bruna7359fd2012-10-17 15:03:11 +02002645 { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun87855892012-10-17 17:39:35 +02002646 { "ssl_f_i_dn", smp_fetch_ssl_f_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun521a0112012-10-22 12:22:55 +02002647 { "ssl_f_key_alg", smp_fetch_ssl_f_key_alg, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brunce5ad802012-10-22 14:11:22 +02002648 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
2649 { "ssl_f_notbefore", smp_fetch_ssl_f_notbefore, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun7f56e742012-10-19 18:15:40 +02002650 { "ssl_f_sig_alg", smp_fetch_ssl_f_sig_alg, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun87855892012-10-17 17:39:35 +02002651 { "ssl_f_s_dn", smp_fetch_ssl_f_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Willy Tarreau8d598402012-10-22 17:58:39 +02002652 { "ssl_f_serial", smp_fetch_ssl_f_serial, 0, NULL, SMP_T_BIN, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Bruna7359fd2012-10-17 15:03:11 +02002653 { "ssl_f_version", smp_fetch_ssl_f_version, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002654 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun589fcad2012-10-16 14:13:26 +02002655 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2656 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002657 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
2658 { "ssl_fc_has_sni", smp_fetch_ssl_fc_has_sni, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
Willy Tarreaua33c6542012-10-15 13:19:06 +02002659#ifdef OPENSSL_NPN_NEGOTIATED
Emeric Brun2525b6b2012-10-18 15:59:43 +02002660 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
Willy Tarreaua33c6542012-10-15 13:19:06 +02002661#endif
Emeric Brun589fcad2012-10-16 14:13:26 +02002662 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
2663 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brunfe68f682012-10-16 14:59:28 +02002664 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_CBIN, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002665 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
Willy Tarreau7875d092012-09-10 08:20:03 +02002666 { NULL, NULL, 0, 0, 0 },
2667}};
2668
2669/* Note: must not be declared <const> as its list will be overwritten.
2670 * Please take care of keeping this list alphabetically sorted.
2671 */
2672static struct acl_kw_list acl_kws = {{ },{
Emeric Brun2525b6b2012-10-18 15:59:43 +02002673 { "ssl_c_ca_err", acl_parse_int, smp_fetch_ssl_c_ca_err, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2674 { "ssl_c_ca_err_depth", acl_parse_int, smp_fetch_ssl_c_ca_err_depth, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2675 { "ssl_c_err", acl_parse_int, smp_fetch_ssl_c_err, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun87855892012-10-17 17:39:35 +02002676 { "ssl_c_i_dn", acl_parse_str, smp_fetch_ssl_c_i_dn, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, ARG2(0,STR,SINT) },
Emeric Brun521a0112012-10-22 12:22:55 +02002677 { "ssl_c_key_alg", acl_parse_str, smp_fetch_ssl_c_key_alg, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brunce5ad802012-10-22 14:11:22 +02002678 { "ssl_c_notafter", acl_parse_str, smp_fetch_ssl_c_notafter, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2679 { "ssl_c_notbefore", acl_parse_str, smp_fetch_ssl_c_notbefore, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun7f56e742012-10-19 18:15:40 +02002680 { "ssl_c_sig_alg", acl_parse_str, smp_fetch_ssl_c_sig_alg, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun87855892012-10-17 17:39:35 +02002681 { "ssl_c_s_dn", acl_parse_str, smp_fetch_ssl_c_s_dn, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, ARG2(0,STR,SINT) },
Willy Tarreau8d598402012-10-22 17:58:39 +02002682 { "ssl_c_serial", acl_parse_bin, smp_fetch_ssl_c_serial, acl_match_bin, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002683 { "ssl_c_verify", acl_parse_int, smp_fetch_ssl_c_verify, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Bruna7359fd2012-10-17 15:03:11 +02002684 { "ssl_c_version", acl_parse_int, smp_fetch_ssl_c_version, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun87855892012-10-17 17:39:35 +02002685 { "ssl_f_i_dn", acl_parse_str, smp_fetch_ssl_f_i_dn, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, ARG2(0,STR,SINT) },
Emeric Brun521a0112012-10-22 12:22:55 +02002686 { "ssl_f_key_alg", acl_parse_str, smp_fetch_ssl_f_key_alg, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brunce5ad802012-10-22 14:11:22 +02002687 { "ssl_f_notafter", acl_parse_str, smp_fetch_ssl_f_notafter, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2688 { "ssl_f_notbefore", acl_parse_str, smp_fetch_ssl_f_notbefore, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun7f56e742012-10-19 18:15:40 +02002689 { "ssl_f_sig_alg", acl_parse_str, smp_fetch_ssl_f_sig_alg, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun87855892012-10-17 17:39:35 +02002690 { "ssl_f_s_dn", acl_parse_str, smp_fetch_ssl_f_s_dn, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, ARG2(0,STR,SINT) },
Willy Tarreau8d598402012-10-22 17:58:39 +02002691 { "ssl_f_serial", acl_parse_bin, smp_fetch_ssl_f_serial, acl_match_bin, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Bruna7359fd2012-10-17 15:03:11 +02002692 { "ssl_f_version", acl_parse_int, smp_fetch_ssl_f_version, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002693 { "ssl_fc", acl_parse_int, smp_fetch_ssl_fc, acl_match_nothing, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun589fcad2012-10-16 14:13:26 +02002694 { "ssl_fc_alg_keysize", acl_parse_str, smp_fetch_ssl_fc_alg_keysize, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2695 { "ssl_fc_cipher", acl_parse_str, smp_fetch_ssl_fc_cipher, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002696 { "ssl_fc_has_crt", acl_parse_int, smp_fetch_ssl_fc_has_crt, acl_match_nothing, ACL_USE_L6REQ_PERMANENT, 0 },
2697 { "ssl_fc_has_sni", acl_parse_int, smp_fetch_ssl_fc_has_sni, acl_match_nothing, ACL_USE_L6REQ_PERMANENT, 0 },
Willy Tarreaua33c6542012-10-15 13:19:06 +02002698#ifdef OPENSSL_NPN_NEGOTIATED
Emeric Brun2525b6b2012-10-18 15:59:43 +02002699 { "ssl_fc_npn", acl_parse_str, smp_fetch_ssl_fc_npn, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Willy Tarreaua33c6542012-10-15 13:19:06 +02002700#endif
Emeric Brun589fcad2012-10-16 14:13:26 +02002701 { "ssl_fc_protocol", acl_parse_str, smp_fetch_ssl_fc_protocol, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2702 { "ssl_fc_use_keysize", acl_parse_str, smp_fetch_ssl_fc_use_keysize, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002703 { "ssl_fc_sni", acl_parse_str, smp_fetch_ssl_fc_sni, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2704 { "ssl_fc_sni_end", acl_parse_str, smp_fetch_ssl_fc_sni, acl_match_end, ACL_USE_L6REQ_PERMANENT, 0 },
2705 { "ssl_fc_sni_reg", acl_parse_reg, smp_fetch_ssl_fc_sni, acl_match_reg, ACL_USE_L6REQ_PERMANENT, 0 },
Willy Tarreau7875d092012-09-10 08:20:03 +02002706 { NULL, NULL, NULL, NULL },
2707}};
2708
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002709/* Note: must not be declared <const> as its list will be overwritten.
2710 * Please take care of keeping this list alphabetically sorted, doing so helps
2711 * all code contributors.
2712 * Optional keywords are also declared with a NULL ->parse() function so that
2713 * the config parser can report an appropriate error when a known keyword was
2714 * not enabled.
2715 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02002716static struct bind_kw_list bind_kws = { "SSL", { }, {
Emeric Brunfb510ea2012-10-05 12:00:26 +02002717 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002718 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
2719 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02002720 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002721 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
2722 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
2723 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002724 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
2725 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
2726 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
2727 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02002728 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
2729 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
2730 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
2731 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002732 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002733 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
2734 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002735 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002736 { NULL, NULL, 0 },
2737}};
Emeric Brun46591952012-05-18 15:47:34 +02002738
Willy Tarreau92faadf2012-10-10 23:04:25 +02002739/* Note: must not be declared <const> as its list will be overwritten.
2740 * Please take care of keeping this list alphabetically sorted, doing so helps
2741 * all code contributors.
2742 * Optional keywords are also declared with a NULL ->parse() function so that
2743 * the config parser can report an appropriate error when a known keyword was
2744 * not enabled.
2745 */
2746static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02002747 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002748 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
2749 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02002750 { "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 +02002751 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002752 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
2753 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
2754 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
2755 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
2756 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
2757 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
2758 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
2759 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02002760 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002761 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02002762 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Willy Tarreau92faadf2012-10-10 23:04:25 +02002763 { NULL, NULL, 0, 0 },
2764}};
2765
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002766/* transport-layer operations for SSL sockets */
2767struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02002768 .snd_buf = ssl_sock_from_buf,
2769 .rcv_buf = ssl_sock_to_buf,
2770 .rcv_pipe = NULL,
2771 .snd_pipe = NULL,
2772 .shutr = NULL,
2773 .shutw = ssl_sock_shutw,
2774 .close = ssl_sock_close,
2775 .init = ssl_sock_init,
2776};
2777
2778__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02002779static void __ssl_sock_init(void)
2780{
Emeric Brun46591952012-05-18 15:47:34 +02002781 STACK_OF(SSL_COMP)* cm;
2782
2783 SSL_library_init();
2784 cm = SSL_COMP_get_compression_methods();
2785 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02002786 sample_register_fetches(&sample_fetch_keywords);
2787 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002788 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02002789 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02002790}
2791
2792/*
2793 * Local variables:
2794 * c-indent-level: 8
2795 * c-basic-offset: 8
2796 * End:
2797 */