blob: f6c410f342ebe46391f6a92376bd688380c3dd01 [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
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100128 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err))
Emeric Brun81c00f02012-09-21 14:31:21 +0200129 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 */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100138 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err))
Emeric Brun81c00f02012-09-21 14:31:21 +0200139 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
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100176 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200177 if (!servername[i])
178 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100179 trash.str[i] = tolower(servername[i]);
180 if (!wildp && (trash.str[i] == '.'))
181 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200182 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100183 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200184
185 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100186 node = ebst_lookup(&s->sni_ctx, trash.str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200187 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
Emeric Brun4f65bff2012-11-16 15:11:00 +0100564 if (global.tune.ssllifetime)
565 SSL_CTX_set_timeout(ctx, global.tune.ssllifetime);
566
Emeric Brunfc0421f2012-09-07 17:30:07 +0200567 shared_context_set_cache(ctx);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200568 if (bind_conf->ciphers &&
569 !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200570 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 +0200571 curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200572 cfgerr++;
573 }
574
575 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200576#ifdef OPENSSL_NPN_NEGOTIATED
577 if (bind_conf->npn_str)
578 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
579#endif
580
Emeric Brunfc0421f2012-09-07 17:30:07 +0200581#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
582 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200583 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200584#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200585#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
586 if (bind_conf->ecdhe) {
587 int i;
588 EC_KEY *ecdh;
589
590 i = OBJ_sn2nid(bind_conf->ecdhe);
591 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
592 Alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
593 curproxy->id, bind_conf->ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
594 cfgerr++;
595 }
596 else {
597 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
598 EC_KEY_free(ecdh);
599 }
600 }
601#endif
602
Emeric Brunfc0421f2012-09-07 17:30:07 +0200603 return cfgerr;
604}
605
Emeric Brun94324a42012-10-11 14:00:19 +0200606/* prepare ssl context from servers options. Returns an error count */
607int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
608{
609 int cfgerr = 0;
610 int options =
611 SSL_OP_ALL | /* all known workarounds for bugs */
612 SSL_OP_NO_SSLv2 |
613 SSL_OP_NO_COMPRESSION;
614 int mode =
615 SSL_MODE_ENABLE_PARTIAL_WRITE |
616 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
617 SSL_MODE_RELEASE_BUFFERS;
618
619 /* Initiate SSL context for current server */
620 srv->ssl_ctx.reused_sess = NULL;
621 if (srv->use_ssl)
622 srv->xprt = &ssl_sock;
623 if (srv->check.use_ssl)
624 srv->check.xprt = &ssl_sock;
625
626 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
627 if (!srv->ssl_ctx.ctx) {
628 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
629 proxy_type_str(curproxy), curproxy->id,
630 srv->id);
631 cfgerr++;
632 return cfgerr;
633 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200634 if (srv->ssl_ctx.client_crt) {
635 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
636 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
637 proxy_type_str(curproxy), curproxy->id,
638 srv->id, srv->ssl_ctx.client_crt);
639 cfgerr++;
640 }
641 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
642 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
643 proxy_type_str(curproxy), curproxy->id,
644 srv->id, srv->ssl_ctx.client_crt);
645 cfgerr++;
646 }
647 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
648 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
649 proxy_type_str(curproxy), curproxy->id,
650 srv->id, srv->ssl_ctx.client_crt);
651 cfgerr++;
652 }
653 }
Emeric Brun94324a42012-10-11 14:00:19 +0200654
655 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
656 options |= SSL_OP_NO_SSLv3;
657 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
658 options |= SSL_OP_NO_TLSv1;
659 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
660 options |= SSL_OP_NO_TLSv1_1;
661 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
662 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200663 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
664 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200665 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
666 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
667 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
668 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
669#if SSL_OP_NO_TLSv1_1
670 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
671 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
672#endif
673#if SSL_OP_NO_TLSv1_2
674 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
675 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
676#endif
677
678 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
679 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Emeric Brunef42d922012-10-11 16:11:36 +0200680 SSL_CTX_set_verify(srv->ssl_ctx.ctx, srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE, NULL);
681 if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
682 if (srv->ssl_ctx.ca_file) {
683 /* load CAfile to verify */
684 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
685 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
686 curproxy->id, srv->id,
687 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
688 cfgerr++;
689 }
690 }
691#ifdef X509_V_FLAG_CRL_CHECK
692 if (srv->ssl_ctx.crl_file) {
693 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
694
695 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
696 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
697 curproxy->id, srv->id,
698 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
699 cfgerr++;
700 }
701 else {
702 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
703 }
704 }
705#endif
706 }
707
Emeric Brun4f65bff2012-11-16 15:11:00 +0100708 if (global.tune.ssllifetime)
709 SSL_CTX_set_timeout(srv->ssl_ctx.ctx, global.tune.ssllifetime);
710
Emeric Brun94324a42012-10-11 14:00:19 +0200711 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
712 if (srv->ssl_ctx.ciphers &&
713 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
714 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
715 curproxy->id, srv->id,
716 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
717 cfgerr++;
718 }
719
720 return cfgerr;
721}
722
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200723/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200724 * be NULL, in which case nothing is done. Returns the number of errors
725 * encountered.
726 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200727int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200728{
729 struct ebmb_node *node;
730 struct sni_ctx *sni;
731 int err = 0;
732
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200733 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200734 return 0;
735
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200736 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200737 while (node) {
738 sni = ebmb_entry(node, struct sni_ctx, name);
739 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200740 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200741 node = ebmb_next(node);
742 }
743
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200744 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200745 while (node) {
746 sni = ebmb_entry(node, struct sni_ctx, name);
747 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200748 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200749 node = ebmb_next(node);
750 }
751 return err;
752}
753
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200754/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200755 * be NULL, in which case nothing is done. The default_ctx is nullified too.
756 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200757void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200758{
759 struct ebmb_node *node, *back;
760 struct sni_ctx *sni;
761
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200762 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200763 return;
764
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200765 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200766 while (node) {
767 sni = ebmb_entry(node, struct sni_ctx, name);
768 back = ebmb_next(node);
769 ebmb_delete(node);
770 if (!sni->order) /* only free the CTX on its first occurrence */
771 SSL_CTX_free(sni->ctx);
772 free(sni);
773 node = back;
774 }
775
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200776 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200777 while (node) {
778 sni = ebmb_entry(node, struct sni_ctx, name);
779 back = ebmb_next(node);
780 ebmb_delete(node);
781 if (!sni->order) /* only free the CTX on its first occurrence */
782 SSL_CTX_free(sni->ctx);
783 free(sni);
784 node = back;
785 }
786
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200787 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +0200788}
789
Emeric Brun46591952012-05-18 15:47:34 +0200790/*
791 * This function is called if SSL * context is not yet allocated. The function
792 * is designed to be called before any other data-layer operation and sets the
793 * handshake flag on the connection. It is safe to call it multiple times.
794 * It returns 0 on success and -1 in error case.
795 */
796static int ssl_sock_init(struct connection *conn)
797{
798 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200799 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200800 return 0;
801
Willy Tarreau403edff2012-09-06 11:58:37 +0200802 if (global.maxsslconn && sslconns >= global.maxsslconn)
803 return -1;
804
Emeric Brun46591952012-05-18 15:47:34 +0200805 /* If it is in client mode initiate SSL session
806 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100807 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200808 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100809 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200810 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200811 return -1;
812
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200813 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100814 if (objt_server(conn->target)->ssl_ctx.reused_sess)
815 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +0200816
817 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200818 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200819
820 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200821 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200822
823 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200824 return 0;
825 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100826 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200827 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100828 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200829 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200830 return -1;
831
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200832 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200833
834 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200835 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200836
Emeric Brune1f38db2012-09-03 20:36:47 +0200837 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200838 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +0200839
Emeric Brun46591952012-05-18 15:47:34 +0200840 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200841 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200842
843 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200844 return 0;
845 }
846 /* don't know how to handle such a target */
847 return -1;
848}
849
850
851/* This is the callback which is used when an SSL handshake is pending. It
852 * updates the FD status if it wants some polling before being called again.
853 * It returns 0 if it fails in a fatal way or needs to poll to go further,
854 * otherwise it returns non-zero and removes itself from the connection's
855 * flags (the bit is provided in <flag> by the caller).
856 */
857int ssl_sock_handshake(struct connection *conn, unsigned int flag)
858{
859 int ret;
860
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200861 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200862 goto out_error;
863
Emeric Brun674b7432012-11-08 19:21:55 +0100864 /* If we use SSL_do_handshake to process a reneg initiated by
865 * the remote peer, it sometimes returns SSL_ERROR_SSL.
866 * Usually SSL_write and SSL_read are used and process implicitly
867 * the reneg handshake.
868 * Here we use SSL_peek as a workaround for reneg.
869 */
870 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
871 char c;
872
873 ret = SSL_peek(conn->xprt_ctx, &c, 1);
874 if (ret <= 0) {
875 /* handshake may have not been completed, let's find why */
876 ret = SSL_get_error(conn->xprt_ctx, ret);
877 if (ret == SSL_ERROR_WANT_WRITE) {
878 /* SSL handshake needs to write, L4 connection may not be ready */
879 __conn_sock_stop_recv(conn);
880 __conn_sock_poll_send(conn);
881 return 0;
882 }
883 else if (ret == SSL_ERROR_WANT_READ) {
884 /* handshake may have been completed but we have
885 * no more data to read.
886 */
887 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
888 ret = 1;
889 goto reneg_ok;
890 }
891 /* SSL handshake needs to read, L4 connection is ready */
892 if (conn->flags & CO_FL_WAIT_L4_CONN)
893 conn->flags &= ~CO_FL_WAIT_L4_CONN;
894 __conn_sock_stop_send(conn);
895 __conn_sock_poll_recv(conn);
896 return 0;
897 }
898 else if (ret == SSL_ERROR_SYSCALL) {
899 /* if errno is null, then connection was successfully established */
900 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
901 conn->flags &= ~CO_FL_WAIT_L4_CONN;
902 goto out_error;
903 }
904 else {
905 /* Fail on all other handshake errors */
906 /* Note: OpenSSL may leave unread bytes in the socket's
907 * buffer, causing an RST to be emitted upon close() on
908 * TCP sockets. We first try to drain possibly pending
909 * data to avoid this as much as possible.
910 */
911 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
912 goto out_error;
913 }
914 }
915 /* read some data: consider handshake completed */
916 goto reneg_ok;
917 }
918
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200919 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200920 if (ret != 1) {
921 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200922 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +0200923
924 if (ret == SSL_ERROR_WANT_WRITE) {
925 /* SSL handshake needs to write, L4 connection may not be ready */
926 __conn_sock_stop_recv(conn);
927 __conn_sock_poll_send(conn);
928 return 0;
929 }
930 else if (ret == SSL_ERROR_WANT_READ) {
931 /* SSL handshake needs to read, L4 connection is ready */
932 if (conn->flags & CO_FL_WAIT_L4_CONN)
933 conn->flags &= ~CO_FL_WAIT_L4_CONN;
934 __conn_sock_stop_send(conn);
935 __conn_sock_poll_recv(conn);
936 return 0;
937 }
Willy Tarreau89230192012-09-28 20:22:13 +0200938 else if (ret == SSL_ERROR_SYSCALL) {
939 /* if errno is null, then connection was successfully established */
940 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
941 conn->flags &= ~CO_FL_WAIT_L4_CONN;
942 goto out_error;
943 }
Emeric Brun46591952012-05-18 15:47:34 +0200944 else {
945 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +0200946 /* Note: OpenSSL may leave unread bytes in the socket's
947 * buffer, causing an RST to be emitted upon close() on
948 * TCP sockets. We first try to drain possibly pending
949 * data to avoid this as much as possible.
950 */
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100951 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Emeric Brun46591952012-05-18 15:47:34 +0200952 goto out_error;
953 }
954 }
955
Emeric Brun674b7432012-11-08 19:21:55 +0100956reneg_ok:
957
Emeric Brun46591952012-05-18 15:47:34 +0200958 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100959 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200960 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +0200961 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100962 if (objt_server(conn->target)->ssl_ctx.reused_sess)
963 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +0200964
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100965 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200966 }
967 }
968
969 /* The connection is now established at both layers, it's time to leave */
970 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
971 return 1;
972
973 out_error:
Emeric Brun9fa89732012-10-04 17:09:56 +0200974 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100975 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
976 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
977 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +0200978 }
979
Emeric Brun46591952012-05-18 15:47:34 +0200980 /* Fail on all other handshake errors */
981 conn->flags |= CO_FL_ERROR;
982 conn->flags &= ~flag;
983 return 0;
984}
985
986/* Receive up to <count> bytes from connection <conn>'s socket and store them
987 * into buffer <buf>. The caller must ensure that <count> is always smaller
988 * than the buffer's size. Only one call to recv() is performed, unless the
989 * buffer wraps, in which case a second call may be performed. The connection's
990 * flags are updated with whatever special event is detected (error, read0,
991 * empty). The caller is responsible for taking care of those events and
992 * avoiding the call if inappropriate. The function does not call the
993 * connection's polling update function, so the caller is responsible for this.
994 */
995static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
996{
997 int ret, done = 0;
998 int try = count;
999
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001000 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001001 goto out_error;
1002
1003 if (conn->flags & CO_FL_HANDSHAKE)
1004 /* a handshake was requested */
1005 return 0;
1006
1007 /* compute the maximum block size we can read at once. */
1008 if (buffer_empty(buf)) {
1009 /* let's realign the buffer to optimize I/O */
1010 buf->p = buf->data;
1011 }
1012 else if (buf->data + buf->o < buf->p &&
1013 buf->p + buf->i < buf->data + buf->size) {
1014 /* remaining space wraps at the end, with a moving limit */
1015 if (try > buf->data + buf->size - (buf->p + buf->i))
1016 try = buf->data + buf->size - (buf->p + buf->i);
1017 }
1018
1019 /* read the largest possible block. For this, we perform only one call
1020 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1021 * in which case we accept to do it once again. A new attempt is made on
1022 * EINTR too.
1023 */
1024 while (try) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001025 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001026 if (conn->flags & CO_FL_ERROR) {
1027 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
1028 break;
1029 }
Emeric Brun46591952012-05-18 15:47:34 +02001030 if (ret > 0) {
1031 buf->i += ret;
1032 done += ret;
1033 if (ret < try)
1034 break;
1035 count -= ret;
1036 try = count;
1037 }
1038 else if (ret == 0) {
1039 goto read0;
1040 }
1041 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001042 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001043 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001044 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001045 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001046 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001047 break;
1048 }
1049 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001050 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1051 /* handshake is running, and it may need to re-enable read */
1052 conn->flags |= CO_FL_SSL_WAIT_HS;
1053 __conn_sock_want_recv(conn);
1054 break;
1055 }
Emeric Brun46591952012-05-18 15:47:34 +02001056 /* we need to poll for retry a read later */
1057 __conn_data_poll_recv(conn);
1058 break;
1059 }
1060 /* otherwise it's a real error */
1061 goto out_error;
1062 }
1063 }
1064 return done;
1065
1066 read0:
1067 conn_sock_read0(conn);
1068 return done;
1069 out_error:
1070 conn->flags |= CO_FL_ERROR;
1071 return done;
1072}
1073
1074
1075/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1076 * <flags> may contain MSG_MORE to make the system hold on without sending
1077 * data too fast, but this flag is ignored at the moment.
1078 * Only one call to send() is performed, unless the buffer wraps, in which case
1079 * a second call may be performed. The connection's flags are updated with
1080 * whatever special event is detected (error, empty). The caller is responsible
1081 * for taking care of those events and avoiding the call if inappropriate. The
1082 * function does not call the connection's polling update function, so the caller
1083 * is responsible for this.
1084 */
1085static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1086{
1087 int ret, try, done;
1088
1089 done = 0;
1090
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001091 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001092 goto out_error;
1093
1094 if (conn->flags & CO_FL_HANDSHAKE)
1095 /* a handshake was requested */
1096 return 0;
1097
1098 /* send the largest possible block. For this we perform only one call
1099 * to send() unless the buffer wraps and we exactly fill the first hunk,
1100 * in which case we accept to do it once again.
1101 */
1102 while (buf->o) {
1103 try = buf->o;
1104 /* outgoing data may wrap at the end */
1105 if (buf->data + try > buf->p)
1106 try = buf->data + try - buf->p;
1107
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001108 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001109 if (conn->flags & CO_FL_ERROR) {
1110 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
1111 break;
1112 }
Emeric Brun46591952012-05-18 15:47:34 +02001113 if (ret > 0) {
1114 buf->o -= ret;
1115 done += ret;
1116
1117 if (likely(!buffer_len(buf)))
1118 /* optimize data alignment in the buffer */
1119 buf->p = buf->data;
1120
1121 /* if the system buffer is full, don't insist */
1122 if (ret < try)
1123 break;
1124 }
1125 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001126 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001127 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001128 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1129 /* handshake is running, and it may need to re-enable write */
1130 conn->flags |= CO_FL_SSL_WAIT_HS;
1131 __conn_sock_want_send(conn);
1132 break;
1133 }
Emeric Brun46591952012-05-18 15:47:34 +02001134 /* we need to poll to retry a write later */
1135 __conn_data_poll_send(conn);
1136 break;
1137 }
1138 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001139 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001140 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001141 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001142 break;
1143 }
1144 goto out_error;
1145 }
1146 }
1147 return done;
1148
1149 out_error:
1150 conn->flags |= CO_FL_ERROR;
1151 return done;
1152}
1153
1154
1155static void ssl_sock_close(struct connection *conn) {
1156
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001157 if (conn->xprt_ctx) {
1158 SSL_free(conn->xprt_ctx);
1159 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001160 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001161 }
Emeric Brun46591952012-05-18 15:47:34 +02001162}
1163
1164/* This function tries to perform a clean shutdown on an SSL connection, and in
1165 * any case, flags the connection as reusable if no handshake was in progress.
1166 */
1167static void ssl_sock_shutw(struct connection *conn, int clean)
1168{
1169 if (conn->flags & CO_FL_HANDSHAKE)
1170 return;
1171 /* no handshake was in progress, try a clean ssl shutdown */
1172 if (clean)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001173 SSL_shutdown(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001174
1175 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001176 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001177}
1178
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001179/* used for logging, may be changed for a sample fetch later */
1180const char *ssl_sock_get_cipher_name(struct connection *conn)
1181{
1182 if (!conn->xprt && !conn->xprt_ctx)
1183 return NULL;
1184 return SSL_get_cipher_name(conn->xprt_ctx);
1185}
1186
1187/* used for logging, may be changed for a sample fetch later */
1188const char *ssl_sock_get_proto_version(struct connection *conn)
1189{
1190 if (!conn->xprt && !conn->xprt_ctx)
1191 return NULL;
1192 return SSL_get_version(conn->xprt_ctx);
1193}
1194
Willy Tarreau8d598402012-10-22 17:58:39 +02001195/* Extract a serial from a cert, and copy it to a chunk.
1196 * Returns 1 if serial is found and copied, 0 if no serial found and
1197 * -1 if output is not large enough.
1198 */
1199static int
1200ssl_sock_get_serial(X509 *crt, struct chunk *out)
1201{
1202 ASN1_INTEGER *serial;
1203
1204 serial = X509_get_serialNumber(crt);
1205 if (!serial)
1206 return 0;
1207
1208 if (out->size < serial->length)
1209 return -1;
1210
1211 memcpy(out->str, serial->data, serial->length);
1212 out->len = serial->length;
1213 return 1;
1214}
1215
Emeric Brunce5ad802012-10-22 14:11:22 +02001216
1217/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1218 * Returns 1 if serial is found and copied, 0 if no valid time found
1219 * and -1 if output is not large enough.
1220 */
1221static int
1222ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1223{
1224 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1225 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1226
1227 if (gentm->length < 12)
1228 return 0;
1229 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1230 return 0;
1231 if (out->size < gentm->length-2)
1232 return -1;
1233
1234 memcpy(out->str, gentm->data+2, gentm->length-2);
1235 out->len = gentm->length-2;
1236 return 1;
1237 }
1238 else if (tm->type == V_ASN1_UTCTIME) {
1239 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1240
1241 if (utctm->length < 10)
1242 return 0;
1243 if (utctm->data[0] >= 0x35)
1244 return 0;
1245 if (out->size < utctm->length)
1246 return -1;
1247
1248 memcpy(out->str, utctm->data, utctm->length);
1249 out->len = utctm->length;
1250 return 1;
1251 }
1252
1253 return 0;
1254}
1255
Emeric Brun87855892012-10-17 17:39:35 +02001256/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1257 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1258 */
1259static int
1260ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1261{
1262 X509_NAME_ENTRY *ne;
1263 int i, j, n;
1264 int cur = 0;
1265 const char *s;
1266 char tmp[128];
1267
1268 out->len = 0;
1269 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1270 if (pos < 0)
1271 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1272 else
1273 j = i;
1274
1275 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1276 n = OBJ_obj2nid(ne->object);
1277 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1278 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1279 s = tmp;
1280 }
1281
1282 if (chunk_strcasecmp(entry, s) != 0)
1283 continue;
1284
1285 if (pos < 0)
1286 cur--;
1287 else
1288 cur++;
1289
1290 if (cur != pos)
1291 continue;
1292
1293 if (ne->value->length > out->size)
1294 return -1;
1295
1296 memcpy(out->str, ne->value->data, ne->value->length);
1297 out->len = ne->value->length;
1298 return 1;
1299 }
1300
1301 return 0;
1302
1303}
1304
1305/* Extract and format full DN from a X509_NAME and copy result into a chunk
1306 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1307 */
1308static int
1309ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1310{
1311 X509_NAME_ENTRY *ne;
1312 int i, n, ln;
1313 int l = 0;
1314 const char *s;
1315 char *p;
1316 char tmp[128];
1317
1318 out->len = 0;
1319 p = out->str;
1320 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1321 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1322 n = OBJ_obj2nid(ne->object);
1323 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1324 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1325 s = tmp;
1326 }
1327 ln = strlen(s);
1328
1329 l += 1 + ln + 1 + ne->value->length;
1330 if (l > out->size)
1331 return -1;
1332 out->len = l;
1333
1334 *(p++)='/';
1335 memcpy(p, s, ln);
1336 p += ln;
1337 *(p++)='=';
1338 memcpy(p, ne->value->data, ne->value->length);
1339 p += ne->value->length;
1340 }
1341
1342 if (!out->len)
1343 return 0;
1344
1345 return 1;
1346}
1347
Willy Tarreau7875d092012-09-10 08:20:03 +02001348/***** Below are some sample fetching functions for ACL/patterns *****/
1349
Emeric Brune64aef12012-09-21 13:15:06 +02001350/* boolean, returns true if client cert was present */
1351static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001352smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1353 const struct arg *args, struct sample *smp)
Emeric Brune64aef12012-09-21 13:15:06 +02001354{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001355 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001356 return 0;
1357
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001358 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001359 smp->flags |= SMP_F_MAY_CHANGE;
1360 return 0;
1361 }
1362
1363 smp->flags = 0;
1364 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001365 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001366
1367 return 1;
1368}
1369
Willy Tarreau8d598402012-10-22 17:58:39 +02001370/* bin, returns serial in a binary chunk */
1371static int
1372smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1373 const struct arg *args, struct sample *smp)
1374{
1375 X509 *crt = NULL;
1376 int ret = 0;
1377 struct chunk *smp_trash;
1378
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001379 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001380 return 0;
1381
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001382 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001383 smp->flags |= SMP_F_MAY_CHANGE;
1384 return 0;
1385 }
1386
1387 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001388 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001389 if (!crt)
1390 goto out;
1391
1392 smp_trash = sample_get_trash_chunk();
1393 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1394 goto out;
1395
1396 smp->data.str = *smp_trash;
1397 smp->type = SMP_T_BIN;
1398 ret = 1;
1399out:
1400 if (crt)
1401 X509_free(crt);
1402 return ret;
1403}
Emeric Brune64aef12012-09-21 13:15:06 +02001404
Emeric Brunce5ad802012-10-22 14:11:22 +02001405/*str, returns notafter date in ASN1_UTCTIME format */
1406static int
1407smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1408 const struct arg *args, struct sample *smp)
1409{
1410 X509 *crt = NULL;
1411 int ret = 0;
1412 struct chunk *smp_trash;
1413
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001414 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001415 return 0;
1416
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001417 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001418 smp->flags |= SMP_F_MAY_CHANGE;
1419 return 0;
1420 }
1421
1422 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001423 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001424 if (!crt)
1425 goto out;
1426
1427 smp_trash = sample_get_trash_chunk();
1428 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1429 goto out;
1430
1431 smp->data.str = *smp_trash;
1432 smp->type = SMP_T_STR;
1433 ret = 1;
1434out:
1435 if (crt)
1436 X509_free(crt);
1437 return ret;
1438}
1439
Emeric Brun87855892012-10-17 17:39:35 +02001440/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1441static int
1442smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1443 const struct arg *args, struct sample *smp)
1444{
1445 X509 *crt = NULL;
1446 X509_NAME *name;
1447 int ret = 0;
1448 struct chunk *smp_trash;
1449
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001450 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001451 return 0;
1452
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001453 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001454 smp->flags |= SMP_F_MAY_CHANGE;
1455 return 0;
1456 }
1457
1458 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001459 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001460 if (!crt)
1461 goto out;
1462
1463 name = X509_get_issuer_name(crt);
1464 if (!name)
1465 goto out;
1466
1467 smp_trash = sample_get_trash_chunk();
1468 if (args && args[0].type == ARGT_STR) {
1469 int pos = 1;
1470
1471 if (args[1].type == ARGT_SINT)
1472 pos = args[1].data.sint;
1473 else if (args[1].type == ARGT_UINT)
1474 pos =(int)args[1].data.uint;
1475
1476 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1477 goto out;
1478 }
1479 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1480 goto out;
1481
1482 smp->type = SMP_T_STR;
1483 smp->data.str = *smp_trash;
1484 ret = 1;
1485out:
1486 if (crt)
1487 X509_free(crt);
1488 return ret;
1489}
1490
Emeric Brunce5ad802012-10-22 14:11:22 +02001491/*str, returns notbefore date in ASN1_UTCTIME format */
1492static int
1493smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1494 const struct arg *args, struct sample *smp)
1495{
1496 X509 *crt = NULL;
1497 int ret = 0;
1498 struct chunk *smp_trash;
1499
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001500 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001501 return 0;
1502
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001503 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001504 smp->flags |= SMP_F_MAY_CHANGE;
1505 return 0;
1506 }
1507
1508 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001509 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001510 if (!crt)
1511 goto out;
1512
1513 smp_trash = sample_get_trash_chunk();
1514 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1515 goto out;
1516
1517 smp->data.str = *smp_trash;
1518 smp->type = SMP_T_STR;
1519 ret = 1;
1520out:
1521 if (crt)
1522 X509_free(crt);
1523 return ret;
1524}
1525
Emeric Brun87855892012-10-17 17:39:35 +02001526/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1527static int
1528smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1529 const struct arg *args, struct sample *smp)
1530{
1531 X509 *crt = NULL;
1532 X509_NAME *name;
1533 int ret = 0;
1534 struct chunk *smp_trash;
1535
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001536 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001537 return 0;
1538
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001539 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001540 smp->flags |= SMP_F_MAY_CHANGE;
1541 return 0;
1542 }
1543
1544 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001545 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001546 if (!crt)
1547 goto out;
1548
1549 name = X509_get_subject_name(crt);
1550 if (!name)
1551 goto out;
1552
1553 smp_trash = sample_get_trash_chunk();
1554 if (args && args[0].type == ARGT_STR) {
1555 int pos = 1;
1556
1557 if (args[1].type == ARGT_SINT)
1558 pos = args[1].data.sint;
1559 else if (args[1].type == ARGT_UINT)
1560 pos =(int)args[1].data.uint;
1561
1562 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1563 goto out;
1564 }
1565 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1566 goto out;
1567
1568 smp->type = SMP_T_STR;
1569 smp->data.str = *smp_trash;
1570 ret = 1;
1571out:
1572 if (crt)
1573 X509_free(crt);
1574 return ret;
1575}
Emeric Bruna7359fd2012-10-17 15:03:11 +02001576/* integer, returns the client certificate version */
1577static int
1578smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1579 const struct arg *args, struct sample *smp)
1580{
1581 X509 *crt;
1582
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001583 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001584 return 0;
1585
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001586 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001587 smp->flags |= SMP_F_MAY_CHANGE;
1588 return 0;
1589 }
1590
1591 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001592 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001593 if (!crt)
1594 return 0;
1595
1596 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1597 X509_free(crt);
1598 smp->type = SMP_T_UINT;
1599
1600 return 1;
1601}
1602
Emeric Brun7f56e742012-10-19 18:15:40 +02001603/* str, returns the client certificate sig alg */
1604static int
1605smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1606 const struct arg *args, struct sample *smp)
1607{
1608 X509 *crt;
1609 int nid;
1610
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001611 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02001612 return 0;
1613
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001614 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02001615 smp->flags |= SMP_F_MAY_CHANGE;
1616 return 0;
1617 }
1618
1619 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001620 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02001621 if (!crt)
1622 return 0;
1623
1624 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1625
1626 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1627 if (!smp->data.str.str)
1628 return 0;
1629
1630 smp->type = SMP_T_CSTR;
1631 smp->data.str.len = strlen(smp->data.str.str);
1632 X509_free(crt);
1633
1634 return 1;
1635}
1636
Emeric Brun521a0112012-10-22 12:22:55 +02001637/* str, returns the client certificate key alg */
1638static int
1639smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1640 const struct arg *args, struct sample *smp)
1641{
1642 X509 *crt;
1643 int nid;
1644
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001645 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02001646 return 0;
1647
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001648 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02001649 smp->flags |= SMP_F_MAY_CHANGE;
1650 return 0;
1651 }
1652
1653 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001654 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02001655 if (!crt)
1656 return 0;
1657
1658 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1659
1660 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1661 if (!smp->data.str.str)
1662 return 0;
1663
1664 smp->type = SMP_T_CSTR;
1665 smp->data.str.len = strlen(smp->data.str.str);
1666 X509_free(crt);
1667
1668 return 1;
1669}
1670
Emeric Brun2525b6b2012-10-18 15:59:43 +02001671/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02001672static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001673smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau7875d092012-09-10 08:20:03 +02001674 const struct arg *args, struct sample *smp)
1675{
1676 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001677 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02001678 return 1;
1679}
1680
Emeric Brun2525b6b2012-10-18 15:59:43 +02001681/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02001682static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001683smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1684 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02001685{
1686#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1687 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001688 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock) &&
1689 l4->si[0].conn->xprt_ctx &&
1690 SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02001691 return 1;
1692#else
1693 return 0;
1694#endif
1695}
1696
Willy Tarreau8d598402012-10-22 17:58:39 +02001697/* bin, returns serial in a binary chunk */
1698static int
1699smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1700 const struct arg *args, struct sample *smp)
1701{
1702 X509 *crt = NULL;
1703 int ret = 0;
1704 struct chunk *smp_trash;
1705
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001706 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001707 return 0;
1708
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001709 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001710 smp->flags |= SMP_F_MAY_CHANGE;
1711 return 0;
1712 }
1713
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001714 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001715 if (!crt)
1716 goto out;
1717
1718 smp_trash = sample_get_trash_chunk();
1719 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1720 goto out;
1721
1722 smp->data.str = *smp_trash;
1723 smp->type = SMP_T_BIN;
1724 ret = 1;
1725out:
1726 return ret;
1727}
Emeric Brunce5ad802012-10-22 14:11:22 +02001728/*str, returns notafter date in ASN1_UTCTIME format */
1729static int
1730smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1731 const struct arg *args, struct sample *smp)
1732{
1733 X509 *crt = NULL;
1734 int ret = 0;
1735 struct chunk *smp_trash;
1736
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001737 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001738 return 0;
1739
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001740 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001741 smp->flags |= SMP_F_MAY_CHANGE;
1742 return 0;
1743 }
1744
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001745 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001746 if (!crt)
1747 goto out;
1748
1749 smp_trash = sample_get_trash_chunk();
1750 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1751 goto out;
1752
1753 smp->data.str = *smp_trash;
1754 smp->type = SMP_T_STR;
1755 ret = 1;
1756out:
1757 return ret;
1758}
1759
1760/*str, returns notbefore date in ASN1_UTCTIME format */
1761static int
1762smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1763 const struct arg *args, struct sample *smp)
1764{
1765 X509 *crt = NULL;
1766 int ret = 0;
1767 struct chunk *smp_trash;
1768
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001769 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001770 return 0;
1771
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001772 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001773 smp->flags |= SMP_F_MAY_CHANGE;
1774 return 0;
1775 }
1776
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001777 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001778 if (!crt)
1779 goto out;
1780
1781 smp_trash = sample_get_trash_chunk();
1782 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1783 goto out;
1784
1785 smp->data.str = *smp_trash;
1786 smp->type = SMP_T_STR;
1787 ret = 1;
1788out:
1789 return ret;
1790}
Willy Tarreau8d598402012-10-22 17:58:39 +02001791
Emeric Bruna7359fd2012-10-17 15:03:11 +02001792/* integer, returns the frontend certificate version */
1793static int
1794smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1795 const struct arg *args, struct sample *smp)
1796{
1797 X509 *crt;
1798
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001799 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001800 return 0;
1801
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001802 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001803 smp->flags |= SMP_F_MAY_CHANGE;
1804 return 0;
1805 }
1806
1807 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001808 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001809 if (!crt)
1810 return 0;
1811
1812 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1813 smp->type = SMP_T_UINT;
1814
1815 return 1;
1816}
1817
Emeric Brun7f56e742012-10-19 18:15:40 +02001818/* str, returns the client certificate sig alg */
1819static int
1820smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1821 const struct arg *args, struct sample *smp)
1822{
1823 X509 *crt;
1824 int nid;
1825
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001826 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02001827 return 0;
1828
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001829 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02001830 smp->flags |= SMP_F_MAY_CHANGE;
1831 return 0;
1832 }
1833
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001834 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02001835 if (!crt)
1836 return 0;
1837
1838 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1839
1840 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1841 if (!smp->data.str.str)
1842 return 0;
1843
1844 smp->type = SMP_T_CSTR;
1845 smp->data.str.len = strlen(smp->data.str.str);
1846
1847 return 1;
1848}
1849
Emeric Brun521a0112012-10-22 12:22:55 +02001850/* str, returns the client certificate key alg */
1851static int
1852smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1853 const struct arg *args, struct sample *smp)
1854{
1855 X509 *crt;
1856 int nid;
1857
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001858 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02001859 return 0;
1860
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001861 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02001862 smp->flags |= SMP_F_MAY_CHANGE;
1863 return 0;
1864 }
1865
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001866 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02001867 if (!crt)
1868 return 0;
1869
1870 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1871
1872 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1873 if (!smp->data.str.str)
1874 return 0;
1875
1876 smp->type = SMP_T_CSTR;
1877 smp->data.str.len = strlen(smp->data.str.str);
1878
1879 return 1;
1880}
1881
Emeric Brun87855892012-10-17 17:39:35 +02001882/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1883static int
1884smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1885 const struct arg *args, struct sample *smp)
1886{
1887 X509 *crt = NULL;
1888 X509_NAME *name;
1889 int ret = 0;
1890 struct chunk *smp_trash;
1891
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001892 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001893 return 0;
1894
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001895 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001896 smp->flags |= SMP_F_MAY_CHANGE;
1897 return 0;
1898 }
1899
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001900 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001901 if (!crt)
1902 goto out;
1903
1904 name = X509_get_issuer_name(crt);
1905 if (!name)
1906 goto out;
1907
1908 smp_trash = sample_get_trash_chunk();
1909 if (args && args[0].type == ARGT_STR) {
1910 int pos = 1;
1911
1912 if (args[1].type == ARGT_SINT)
1913 pos = args[1].data.sint;
1914 else if (args[1].type == ARGT_UINT)
1915 pos =(int)args[1].data.uint;
1916
1917 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1918 goto out;
1919 }
1920 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1921 goto out;
1922
1923 smp->type = SMP_T_STR;
1924 smp->data.str = *smp_trash;
1925 ret = 1;
1926out:
1927 return ret;
1928}
1929
1930/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1931static int
1932smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1933 const struct arg *args, struct sample *smp)
1934{
1935 X509 *crt = NULL;
1936 X509_NAME *name;
1937 int ret = 0;
1938 struct chunk *smp_trash;
1939
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001940 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001941 return 0;
1942
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001943 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001944 smp->flags |= SMP_F_MAY_CHANGE;
1945 return 0;
1946 }
1947
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001948 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001949 if (!crt)
1950 goto out;
1951
1952 name = X509_get_subject_name(crt);
1953 if (!name)
1954 goto out;
1955
1956 smp_trash = sample_get_trash_chunk();
1957 if (args && args[0].type == ARGT_STR) {
1958 int pos = 1;
1959
1960 if (args[1].type == ARGT_SINT)
1961 pos = args[1].data.sint;
1962 else if (args[1].type == ARGT_UINT)
1963 pos =(int)args[1].data.uint;
1964
1965 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1966 goto out;
1967 }
1968 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1969 goto out;
1970
1971 smp->type = SMP_T_STR;
1972 smp->data.str = *smp_trash;
1973 ret = 1;
1974out:
1975 return ret;
1976}
1977
Emeric Brun589fcad2012-10-16 14:13:26 +02001978static int
1979smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1980 const struct arg *args, struct sample *smp)
1981{
1982 smp->flags = 0;
1983
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001984 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02001985 return 0;
1986
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001987 smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02001988 if (!smp->data.str.str)
1989 return 0;
1990
1991 smp->type = SMP_T_CSTR;
1992 smp->data.str.len = strlen(smp->data.str.str);
1993
1994 return 1;
1995}
1996
1997static int
1998smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1999 const struct arg *args, struct sample *smp)
2000{
2001 smp->flags = 0;
2002
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002003 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002004 return 0;
2005
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002006 if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
Emeric Brun589fcad2012-10-16 14:13:26 +02002007 return 0;
2008
2009 smp->type = SMP_T_UINT;
2010
2011 return 1;
2012}
2013
2014static int
2015smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2016 const struct arg *args, struct sample *smp)
2017{
2018 smp->flags = 0;
2019
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002020 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002021 return 0;
2022
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002023 smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002024 if (!smp->data.uint)
2025 return 0;
2026
2027 smp->type = SMP_T_UINT;
2028
2029 return 1;
2030}
2031
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002032#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002033static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002034smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2035 const struct arg *args, struct sample *smp)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002036{
Willy Tarreaua33c6542012-10-15 13:19:06 +02002037 smp->flags = 0;
2038 smp->type = SMP_T_CSTR;
2039
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002040 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002041 return 0;
2042
2043 smp->data.str.str = NULL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002044 SSL_get0_next_proto_negotiated(l4->si[0].conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002045 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2046
2047 if (!smp->data.str.str)
2048 return 0;
2049
2050 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002051}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002052#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002053
2054static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002055smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2056 const struct arg *args, struct sample *smp)
2057{
2058 smp->flags = 0;
2059
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002060 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002061 return 0;
2062
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002063 smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002064 if (!smp->data.str.str)
2065 return 0;
2066
2067 smp->type = SMP_T_CSTR;
2068 smp->data.str.len = strlen(smp->data.str.str);
2069
2070 return 1;
2071}
2072
2073static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002074smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2075 const struct arg *args, struct sample *smp)
2076{
2077#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2078 SSL_SESSION *sess;
2079
2080 smp->flags = 0;
2081 smp->type = SMP_T_CBIN;
2082
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002083 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunfe68f682012-10-16 14:59:28 +02002084 return 0;
2085
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002086 sess = SSL_get_session(l4->si[0].conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002087 if (!sess)
2088 return 0;
2089
2090 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2091 if (!smp->data.str.str || !&smp->data.str.len)
2092 return 0;
2093
2094 return 1;
2095#else
2096 return 0;
2097#endif
2098}
2099
2100static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002101smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2102 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02002103{
2104#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2105 smp->flags = 0;
2106 smp->type = SMP_T_CSTR;
2107
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002108 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau7875d092012-09-10 08:20:03 +02002109 return 0;
2110
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002111 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 +02002112 if (!smp->data.str.str)
2113 return 0;
2114
Willy Tarreau7875d092012-09-10 08:20:03 +02002115 smp->data.str.len = strlen(smp->data.str.str);
2116 return 1;
2117#else
2118 return 0;
2119#endif
2120}
2121
Emeric Brun2525b6b2012-10-18 15:59:43 +02002122/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002123static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002124smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002125 const struct arg *args, struct sample *smp)
2126{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002127 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002128 return 0;
2129
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002130 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002131 smp->flags = SMP_F_MAY_CHANGE;
2132 return 0;
2133 }
2134
2135 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002136 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002137 smp->flags = 0;
2138
2139 return 1;
2140}
2141
Emeric Brun2525b6b2012-10-18 15:59:43 +02002142/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002143static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002144smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002145 const struct arg *args, struct sample *smp)
2146{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002147 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002148 return 0;
2149
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002150 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002151 smp->flags = SMP_F_MAY_CHANGE;
2152 return 0;
2153 }
2154
2155 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002156 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002157 smp->flags = 0;
2158
2159 return 1;
2160}
2161
Emeric Brun2525b6b2012-10-18 15:59:43 +02002162/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002163static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002164smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2165 const struct arg *args, struct sample *smp)
Emeric Brunf282a812012-09-21 15:27:54 +02002166{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002167 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002168 return 0;
2169
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002170 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002171 smp->flags = SMP_F_MAY_CHANGE;
2172 return 0;
2173 }
2174
2175 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002176 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002177 smp->flags = 0;
2178
2179 return 1;
2180}
2181
Emeric Brun2525b6b2012-10-18 15:59:43 +02002182/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002183static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002184smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2185 const struct arg *args, struct sample *smp)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002186{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002187 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002188 return 0;
2189
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002190 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002191 smp->flags = SMP_F_MAY_CHANGE;
2192 return 0;
2193 }
2194
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002195 if (!l4->si[0].conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002196 return 0;
2197
2198 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002199 smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002200 smp->flags = 0;
2201
2202 return 1;
2203}
2204
Emeric Brunfb510ea2012-10-05 12:00:26 +02002205/* parse the "ca-file" bind keyword */
2206static 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 +02002207{
2208 if (!*args[cur_arg + 1]) {
2209 if (err)
2210 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2211 return ERR_ALERT | ERR_FATAL;
2212 }
2213
Emeric Brunef42d922012-10-11 16:11:36 +02002214 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2215 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2216 else
2217 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002218
Emeric Brund94b3fe2012-09-20 18:23:56 +02002219 return 0;
2220}
2221
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002222/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002223static 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 +02002224{
2225 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002226 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002227 return ERR_ALERT | ERR_FATAL;
2228 }
2229
Emeric Brun76d88952012-10-05 15:47:31 +02002230 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002231 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002232 return 0;
2233}
2234
2235/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002236static 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 +02002237{
Emeric Brunc8e8d122012-10-02 18:42:10 +02002238 char path[PATH_MAX];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002239 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002240 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002241 return ERR_ALERT | ERR_FATAL;
2242 }
2243
Emeric Brunc8e8d122012-10-02 18:42:10 +02002244 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
2245 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > PATH_MAX) {
2246 memprintf(err, "'%s' : path too long", args[cur_arg]);
2247 return ERR_ALERT | ERR_FATAL;
2248 }
2249 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2250 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2251 return ERR_ALERT | ERR_FATAL;
2252
2253 return 0;
2254 }
2255
Willy Tarreau4348fad2012-09-20 16:48:07 +02002256 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002257 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002258
2259 return 0;
2260}
2261
Emeric Brunfb510ea2012-10-05 12:00:26 +02002262/* parse the "crl-file" bind keyword */
2263static 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 +02002264{
Emeric Brun051cdab2012-10-02 19:25:50 +02002265#ifndef X509_V_FLAG_CRL_CHECK
2266 if (err)
2267 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2268 return ERR_ALERT | ERR_FATAL;
2269#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002270 if (!*args[cur_arg + 1]) {
2271 if (err)
2272 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2273 return ERR_ALERT | ERR_FATAL;
2274 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002275
Emeric Brunef42d922012-10-11 16:11:36 +02002276 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2277 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2278 else
2279 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002280
Emeric Brun2b58d042012-09-20 17:10:03 +02002281 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002282#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002283}
2284
2285/* parse the "ecdhe" bind keyword keywords */
2286static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2287{
2288#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2289 if (err)
2290 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2291 return ERR_ALERT | ERR_FATAL;
2292#elif defined(OPENSSL_NO_ECDH)
2293 if (err)
2294 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2295 return ERR_ALERT | ERR_FATAL;
2296#else
2297 if (!*args[cur_arg + 1]) {
2298 if (err)
2299 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2300 return ERR_ALERT | ERR_FATAL;
2301 }
2302
2303 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002304
2305 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002306#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002307}
2308
Emeric Brun81c00f02012-09-21 14:31:21 +02002309/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2310static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2311{
2312 int code;
2313 char *p = args[cur_arg + 1];
2314 unsigned long long *ignerr = &conf->crt_ignerr;
2315
2316 if (!*p) {
2317 if (err)
2318 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2319 return ERR_ALERT | ERR_FATAL;
2320 }
2321
2322 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2323 ignerr = &conf->ca_ignerr;
2324
2325 if (strcmp(p, "all") == 0) {
2326 *ignerr = ~0ULL;
2327 return 0;
2328 }
2329
2330 while (p) {
2331 code = atoi(p);
2332 if ((code <= 0) || (code > 63)) {
2333 if (err)
2334 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2335 args[cur_arg], code, args[cur_arg + 1]);
2336 return ERR_ALERT | ERR_FATAL;
2337 }
2338 *ignerr |= 1ULL << code;
2339 p = strchr(p, ',');
2340 if (p)
2341 p++;
2342 }
2343
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002344 return 0;
2345}
2346
2347/* parse the "force-sslv3" bind keyword */
2348static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2349{
2350 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2351 return 0;
2352}
2353
2354/* parse the "force-tlsv10" bind keyword */
2355static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2356{
2357 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002358 return 0;
2359}
2360
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002361/* parse the "force-tlsv11" bind keyword */
2362static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2363{
2364#if SSL_OP_NO_TLSv1_1
2365 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
2366 return 0;
2367#else
2368 if (err)
2369 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
2370 return ERR_ALERT | ERR_FATAL;
2371#endif
2372}
2373
2374/* parse the "force-tlsv12" bind keyword */
2375static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2376{
2377#if SSL_OP_NO_TLSv1_2
2378 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
2379 return 0;
2380#else
2381 if (err)
2382 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
2383 return ERR_ALERT | ERR_FATAL;
2384#endif
2385}
2386
2387
Emeric Brun2d0c4822012-10-02 13:45:20 +02002388/* parse the "no-tls-tickets" bind keyword */
2389static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2390{
Emeric Brun89675492012-10-05 13:48:26 +02002391 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02002392 return 0;
2393}
2394
Emeric Brun2d0c4822012-10-02 13:45:20 +02002395
Emeric Brun9b3009b2012-10-05 11:55:06 +02002396/* parse the "no-sslv3" bind keyword */
2397static 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 +02002398{
Emeric Brun89675492012-10-05 13:48:26 +02002399 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002400 return 0;
2401}
2402
Emeric Brun9b3009b2012-10-05 11:55:06 +02002403/* parse the "no-tlsv10" bind keyword */
2404static 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 +02002405{
Emeric Brun89675492012-10-05 13:48:26 +02002406 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002407 return 0;
2408}
2409
Emeric Brun9b3009b2012-10-05 11:55:06 +02002410/* parse the "no-tlsv11" bind keyword */
2411static 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 +02002412{
Emeric Brun89675492012-10-05 13:48:26 +02002413 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002414 return 0;
2415}
2416
Emeric Brun9b3009b2012-10-05 11:55:06 +02002417/* parse the "no-tlsv12" bind keyword */
2418static 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 +02002419{
Emeric Brun89675492012-10-05 13:48:26 +02002420 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002421 return 0;
2422}
2423
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002424/* parse the "npn" bind keyword */
2425static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2426{
2427#ifdef OPENSSL_NPN_NEGOTIATED
2428 char *p1, *p2;
2429
2430 if (!*args[cur_arg + 1]) {
2431 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
2432 return ERR_ALERT | ERR_FATAL;
2433 }
2434
2435 free(conf->npn_str);
2436
2437 /* the NPN string is built as a suite of (<len> <name>)* */
2438 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
2439 conf->npn_str = calloc(1, conf->npn_len);
2440 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
2441
2442 /* replace commas with the name length */
2443 p1 = conf->npn_str;
2444 p2 = p1 + 1;
2445 while (1) {
2446 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
2447 if (!p2)
2448 p2 = p1 + 1 + strlen(p1 + 1);
2449
2450 if (p2 - (p1 + 1) > 255) {
2451 *p2 = '\0';
2452 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2453 return ERR_ALERT | ERR_FATAL;
2454 }
2455
2456 *p1 = p2 - (p1 + 1);
2457 p1 = p2;
2458
2459 if (!*p2)
2460 break;
2461
2462 *(p2++) = '\0';
2463 }
2464 return 0;
2465#else
2466 if (err)
2467 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
2468 return ERR_ALERT | ERR_FATAL;
2469#endif
2470}
2471
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002472/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002473static 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 +02002474{
Willy Tarreau81796be2012-09-22 19:11:47 +02002475 struct listener *l;
2476
Willy Tarreau4348fad2012-09-20 16:48:07 +02002477 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02002478
2479 if (global.listen_default_ciphers && !conf->ciphers)
2480 conf->ciphers = strdup(global.listen_default_ciphers);
2481
Willy Tarreau81796be2012-09-22 19:11:47 +02002482 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002483 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02002484
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002485 return 0;
2486}
2487
Emeric Brund94b3fe2012-09-20 18:23:56 +02002488/* parse the "verify" bind keyword */
2489static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2490{
2491 if (!*args[cur_arg + 1]) {
2492 if (err)
2493 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
2494 return ERR_ALERT | ERR_FATAL;
2495 }
2496
2497 if (strcmp(args[cur_arg + 1], "none") == 0)
2498 conf->verify = SSL_VERIFY_NONE;
2499 else if (strcmp(args[cur_arg + 1], "optional") == 0)
2500 conf->verify = SSL_VERIFY_PEER;
2501 else if (strcmp(args[cur_arg + 1], "required") == 0)
2502 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2503 else {
2504 if (err)
2505 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
2506 args[cur_arg], args[cur_arg + 1]);
2507 return ERR_ALERT | ERR_FATAL;
2508 }
2509
2510 return 0;
2511}
2512
Willy Tarreau92faadf2012-10-10 23:04:25 +02002513/************** "server" keywords ****************/
2514
Emeric Brunef42d922012-10-11 16:11:36 +02002515/* parse the "ca-file" server keyword */
2516static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2517{
2518 if (!*args[*cur_arg + 1]) {
2519 if (err)
2520 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
2521 return ERR_ALERT | ERR_FATAL;
2522 }
2523
2524 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2525 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2526 else
2527 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
2528
2529 return 0;
2530}
2531
Willy Tarreau92faadf2012-10-10 23:04:25 +02002532/* parse the "check-ssl" server keyword */
2533static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2534{
2535 newsrv->check.use_ssl = 1;
2536 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2537 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2538 return 0;
2539}
2540
2541/* parse the "ciphers" server keyword */
2542static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2543{
2544 if (!*args[*cur_arg + 1]) {
2545 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
2546 return ERR_ALERT | ERR_FATAL;
2547 }
2548
2549 free(newsrv->ssl_ctx.ciphers);
2550 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
2551 return 0;
2552}
2553
Emeric Brunef42d922012-10-11 16:11:36 +02002554/* parse the "crl-file" server keyword */
2555static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2556{
2557#ifndef X509_V_FLAG_CRL_CHECK
2558 if (err)
2559 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
2560 return ERR_ALERT | ERR_FATAL;
2561#else
2562 if (!*args[*cur_arg + 1]) {
2563 if (err)
2564 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
2565 return ERR_ALERT | ERR_FATAL;
2566 }
2567
2568 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2569 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2570 else
2571 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
2572
2573 return 0;
2574#endif
2575}
2576
Emeric Bruna7aa3092012-10-26 12:58:00 +02002577/* parse the "crt" server keyword */
2578static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2579{
2580 if (!*args[*cur_arg + 1]) {
2581 if (err)
2582 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
2583 return ERR_ALERT | ERR_FATAL;
2584 }
2585
2586 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
2587 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2588 else
2589 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
2590
2591 return 0;
2592}
Emeric Brunef42d922012-10-11 16:11:36 +02002593
Willy Tarreau92faadf2012-10-10 23:04:25 +02002594/* parse the "force-sslv3" server keyword */
2595static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2596{
2597 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
2598 return 0;
2599}
2600
2601/* parse the "force-tlsv10" server keyword */
2602static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2603{
2604 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
2605 return 0;
2606}
2607
2608/* parse the "force-tlsv11" server keyword */
2609static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2610{
2611#if SSL_OP_NO_TLSv1_1
2612 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
2613 return 0;
2614#else
2615 if (err)
2616 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
2617 return ERR_ALERT | ERR_FATAL;
2618#endif
2619}
2620
2621/* parse the "force-tlsv12" server keyword */
2622static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2623{
2624#if SSL_OP_NO_TLSv1_2
2625 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
2626 return 0;
2627#else
2628 if (err)
2629 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
2630 return ERR_ALERT | ERR_FATAL;
2631#endif
2632}
2633
2634/* parse the "no-sslv3" server keyword */
2635static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2636{
2637 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
2638 return 0;
2639}
2640
2641/* parse the "no-tlsv10" server keyword */
2642static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2643{
2644 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
2645 return 0;
2646}
2647
2648/* parse the "no-tlsv11" server keyword */
2649static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2650{
2651 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
2652 return 0;
2653}
2654
2655/* parse the "no-tlsv12" server keyword */
2656static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2657{
2658 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
2659 return 0;
2660}
2661
Emeric Brunf9c5c472012-10-11 15:28:34 +02002662/* parse the "no-tls-tickets" server keyword */
2663static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2664{
2665 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
2666 return 0;
2667}
2668
Willy Tarreau92faadf2012-10-10 23:04:25 +02002669/* parse the "ssl" server keyword */
2670static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2671{
2672 newsrv->use_ssl = 1;
2673 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2674 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2675 return 0;
2676}
2677
Emeric Brunef42d922012-10-11 16:11:36 +02002678/* parse the "verify" server keyword */
2679static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2680{
2681 if (!*args[*cur_arg + 1]) {
2682 if (err)
2683 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
2684 return ERR_ALERT | ERR_FATAL;
2685 }
2686
2687 if (strcmp(args[*cur_arg + 1], "none") == 0)
2688 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
2689 else if (strcmp(args[*cur_arg + 1], "required") == 0)
2690 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
2691 else {
2692 if (err)
2693 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
2694 args[*cur_arg], args[*cur_arg + 1]);
2695 return ERR_ALERT | ERR_FATAL;
2696 }
2697
2698 return 0;
2699}
2700
Willy Tarreau7875d092012-09-10 08:20:03 +02002701/* Note: must not be declared <const> as its list will be overwritten.
2702 * Please take care of keeping this list alphabetically sorted.
2703 */
2704static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
Emeric Brun2525b6b2012-10-18 15:59:43 +02002705 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2706 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2707 { "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 +02002708 { "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 +02002709 { "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 +02002710 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
2711 { "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 +02002712 { "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 +02002713 { "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 +02002714 { "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 +02002715 { "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 +02002716 { "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 +02002717 { "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 +02002718 { "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 +02002719 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
2720 { "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 +02002721 { "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 +02002722 { "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 +02002723 { "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 +02002724 { "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 +02002725 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun589fcad2012-10-16 14:13:26 +02002726 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2727 { "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 +02002728 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
2729 { "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 +02002730#ifdef OPENSSL_NPN_NEGOTIATED
Emeric Brun2525b6b2012-10-18 15:59:43 +02002731 { "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 +02002732#endif
Emeric Brun589fcad2012-10-16 14:13:26 +02002733 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
2734 { "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 +02002735 { "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 +02002736 { "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 +02002737 { NULL, NULL, 0, 0, 0 },
2738}};
2739
2740/* Note: must not be declared <const> as its list will be overwritten.
2741 * Please take care of keeping this list alphabetically sorted.
2742 */
2743static struct acl_kw_list acl_kws = {{ },{
Emeric Brun2525b6b2012-10-18 15:59:43 +02002744 { "ssl_c_ca_err", acl_parse_int, smp_fetch_ssl_c_ca_err, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2745 { "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 },
2746 { "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 +02002747 { "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 +02002748 { "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 +02002749 { "ssl_c_notafter", acl_parse_str, smp_fetch_ssl_c_notafter, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2750 { "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 +02002751 { "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 +02002752 { "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 +02002753 { "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 +02002754 { "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 +02002755 { "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 +02002756 { "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 +02002757 { "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 +02002758 { "ssl_f_notafter", acl_parse_str, smp_fetch_ssl_f_notafter, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2759 { "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 +02002760 { "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 +02002761 { "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 +02002762 { "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 +02002763 { "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 +02002764 { "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 +02002765 { "ssl_fc_alg_keysize", acl_parse_str, smp_fetch_ssl_fc_alg_keysize, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2766 { "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 +02002767 { "ssl_fc_has_crt", acl_parse_int, smp_fetch_ssl_fc_has_crt, acl_match_nothing, ACL_USE_L6REQ_PERMANENT, 0 },
2768 { "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 +02002769#ifdef OPENSSL_NPN_NEGOTIATED
Emeric Brun2525b6b2012-10-18 15:59:43 +02002770 { "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 +02002771#endif
Emeric Brun589fcad2012-10-16 14:13:26 +02002772 { "ssl_fc_protocol", acl_parse_str, smp_fetch_ssl_fc_protocol, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2773 { "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 +02002774 { "ssl_fc_sni", acl_parse_str, smp_fetch_ssl_fc_sni, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2775 { "ssl_fc_sni_end", acl_parse_str, smp_fetch_ssl_fc_sni, acl_match_end, ACL_USE_L6REQ_PERMANENT, 0 },
2776 { "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 +02002777 { NULL, NULL, NULL, NULL },
2778}};
2779
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002780/* Note: must not be declared <const> as its list will be overwritten.
2781 * Please take care of keeping this list alphabetically sorted, doing so helps
2782 * all code contributors.
2783 * Optional keywords are also declared with a NULL ->parse() function so that
2784 * the config parser can report an appropriate error when a known keyword was
2785 * not enabled.
2786 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02002787static struct bind_kw_list bind_kws = { "SSL", { }, {
Emeric Brunfb510ea2012-10-05 12:00:26 +02002788 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002789 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
2790 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02002791 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002792 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
2793 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
2794 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002795 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
2796 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
2797 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
2798 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02002799 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
2800 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
2801 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
2802 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002803 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002804 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
2805 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002806 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002807 { NULL, NULL, 0 },
2808}};
Emeric Brun46591952012-05-18 15:47:34 +02002809
Willy Tarreau92faadf2012-10-10 23:04:25 +02002810/* Note: must not be declared <const> as its list will be overwritten.
2811 * Please take care of keeping this list alphabetically sorted, doing so helps
2812 * all code contributors.
2813 * Optional keywords are also declared with a NULL ->parse() function so that
2814 * the config parser can report an appropriate error when a known keyword was
2815 * not enabled.
2816 */
2817static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02002818 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002819 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
2820 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02002821 { "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 +02002822 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002823 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
2824 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
2825 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
2826 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
2827 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
2828 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
2829 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
2830 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02002831 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002832 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02002833 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Willy Tarreau92faadf2012-10-10 23:04:25 +02002834 { NULL, NULL, 0, 0 },
2835}};
2836
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002837/* transport-layer operations for SSL sockets */
2838struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02002839 .snd_buf = ssl_sock_from_buf,
2840 .rcv_buf = ssl_sock_to_buf,
2841 .rcv_pipe = NULL,
2842 .snd_pipe = NULL,
2843 .shutr = NULL,
2844 .shutw = ssl_sock_shutw,
2845 .close = ssl_sock_close,
2846 .init = ssl_sock_init,
2847};
2848
2849__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02002850static void __ssl_sock_init(void)
2851{
Emeric Brun46591952012-05-18 15:47:34 +02002852 STACK_OF(SSL_COMP)* cm;
2853
2854 SSL_library_init();
2855 cm = SSL_COMP_get_compression_methods();
2856 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02002857 sample_register_fetches(&sample_fetch_keywords);
2858 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002859 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02002860 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02002861}
2862
2863/*
2864 * Local variables:
2865 * c-indent-level: 8
2866 * c-basic-offset: 8
2867 * End:
2868 */