blob: 75f7b5d88171437fccd0c870bc4fa2594433bc38 [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
564 shared_context_set_cache(ctx);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200565 if (bind_conf->ciphers &&
566 !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200567 Alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200568 curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200569 cfgerr++;
570 }
571
572 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200573#ifdef OPENSSL_NPN_NEGOTIATED
574 if (bind_conf->npn_str)
575 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
576#endif
577
Emeric Brunfc0421f2012-09-07 17:30:07 +0200578#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
579 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200580 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200581#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200582#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
583 if (bind_conf->ecdhe) {
584 int i;
585 EC_KEY *ecdh;
586
587 i = OBJ_sn2nid(bind_conf->ecdhe);
588 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
589 Alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
590 curproxy->id, bind_conf->ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
591 cfgerr++;
592 }
593 else {
594 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
595 EC_KEY_free(ecdh);
596 }
597 }
598#endif
599
Emeric Brunfc0421f2012-09-07 17:30:07 +0200600 return cfgerr;
601}
602
Emeric Brun94324a42012-10-11 14:00:19 +0200603/* prepare ssl context from servers options. Returns an error count */
604int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
605{
606 int cfgerr = 0;
607 int options =
608 SSL_OP_ALL | /* all known workarounds for bugs */
609 SSL_OP_NO_SSLv2 |
610 SSL_OP_NO_COMPRESSION;
611 int mode =
612 SSL_MODE_ENABLE_PARTIAL_WRITE |
613 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
614 SSL_MODE_RELEASE_BUFFERS;
615
616 /* Initiate SSL context for current server */
617 srv->ssl_ctx.reused_sess = NULL;
618 if (srv->use_ssl)
619 srv->xprt = &ssl_sock;
620 if (srv->check.use_ssl)
621 srv->check.xprt = &ssl_sock;
622
623 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
624 if (!srv->ssl_ctx.ctx) {
625 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
626 proxy_type_str(curproxy), curproxy->id,
627 srv->id);
628 cfgerr++;
629 return cfgerr;
630 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200631 if (srv->ssl_ctx.client_crt) {
632 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
633 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
634 proxy_type_str(curproxy), curproxy->id,
635 srv->id, srv->ssl_ctx.client_crt);
636 cfgerr++;
637 }
638 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
639 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
640 proxy_type_str(curproxy), curproxy->id,
641 srv->id, srv->ssl_ctx.client_crt);
642 cfgerr++;
643 }
644 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
645 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
646 proxy_type_str(curproxy), curproxy->id,
647 srv->id, srv->ssl_ctx.client_crt);
648 cfgerr++;
649 }
650 }
Emeric Brun94324a42012-10-11 14:00:19 +0200651
652 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
653 options |= SSL_OP_NO_SSLv3;
654 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
655 options |= SSL_OP_NO_TLSv1;
656 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
657 options |= SSL_OP_NO_TLSv1_1;
658 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
659 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200660 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
661 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200662 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
663 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
664 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
665 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
666#if SSL_OP_NO_TLSv1_1
667 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
668 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
669#endif
670#if SSL_OP_NO_TLSv1_2
671 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
672 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
673#endif
674
675 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
676 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Emeric Brunef42d922012-10-11 16:11:36 +0200677 SSL_CTX_set_verify(srv->ssl_ctx.ctx, srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE, NULL);
678 if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
679 if (srv->ssl_ctx.ca_file) {
680 /* load CAfile to verify */
681 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
682 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
683 curproxy->id, srv->id,
684 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
685 cfgerr++;
686 }
687 }
688#ifdef X509_V_FLAG_CRL_CHECK
689 if (srv->ssl_ctx.crl_file) {
690 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
691
692 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
693 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
694 curproxy->id, srv->id,
695 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
696 cfgerr++;
697 }
698 else {
699 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
700 }
701 }
702#endif
703 }
704
Emeric Brun94324a42012-10-11 14:00:19 +0200705 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
706 if (srv->ssl_ctx.ciphers &&
707 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
708 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
709 curproxy->id, srv->id,
710 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
711 cfgerr++;
712 }
713
714 return cfgerr;
715}
716
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200717/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200718 * be NULL, in which case nothing is done. Returns the number of errors
719 * encountered.
720 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200721int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200722{
723 struct ebmb_node *node;
724 struct sni_ctx *sni;
725 int err = 0;
726
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200727 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200728 return 0;
729
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200730 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200731 while (node) {
732 sni = ebmb_entry(node, struct sni_ctx, name);
733 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200734 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200735 node = ebmb_next(node);
736 }
737
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200738 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200739 while (node) {
740 sni = ebmb_entry(node, struct sni_ctx, name);
741 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200742 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200743 node = ebmb_next(node);
744 }
745 return err;
746}
747
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200748/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200749 * be NULL, in which case nothing is done. The default_ctx is nullified too.
750 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200751void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200752{
753 struct ebmb_node *node, *back;
754 struct sni_ctx *sni;
755
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200756 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200757 return;
758
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200759 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200760 while (node) {
761 sni = ebmb_entry(node, struct sni_ctx, name);
762 back = ebmb_next(node);
763 ebmb_delete(node);
764 if (!sni->order) /* only free the CTX on its first occurrence */
765 SSL_CTX_free(sni->ctx);
766 free(sni);
767 node = back;
768 }
769
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200770 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200771 while (node) {
772 sni = ebmb_entry(node, struct sni_ctx, name);
773 back = ebmb_next(node);
774 ebmb_delete(node);
775 if (!sni->order) /* only free the CTX on its first occurrence */
776 SSL_CTX_free(sni->ctx);
777 free(sni);
778 node = back;
779 }
780
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200781 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +0200782}
783
Emeric Brun46591952012-05-18 15:47:34 +0200784/*
785 * This function is called if SSL * context is not yet allocated. The function
786 * is designed to be called before any other data-layer operation and sets the
787 * handshake flag on the connection. It is safe to call it multiple times.
788 * It returns 0 on success and -1 in error case.
789 */
790static int ssl_sock_init(struct connection *conn)
791{
792 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200793 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200794 return 0;
795
Willy Tarreau403edff2012-09-06 11:58:37 +0200796 if (global.maxsslconn && sslconns >= global.maxsslconn)
797 return -1;
798
Emeric Brun46591952012-05-18 15:47:34 +0200799 /* If it is in client mode initiate SSL session
800 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100801 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200802 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100803 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200804 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200805 return -1;
806
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200807 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100808 if (objt_server(conn->target)->ssl_ctx.reused_sess)
809 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +0200810
811 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200812 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200813
814 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200815 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200816
817 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200818 return 0;
819 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100820 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200821 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100822 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200823 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200824 return -1;
825
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200826 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200827
828 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200829 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200830
Emeric Brune1f38db2012-09-03 20:36:47 +0200831 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200832 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +0200833
Emeric Brun46591952012-05-18 15:47:34 +0200834 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200835 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200836
837 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200838 return 0;
839 }
840 /* don't know how to handle such a target */
841 return -1;
842}
843
844
845/* This is the callback which is used when an SSL handshake is pending. It
846 * updates the FD status if it wants some polling before being called again.
847 * It returns 0 if it fails in a fatal way or needs to poll to go further,
848 * otherwise it returns non-zero and removes itself from the connection's
849 * flags (the bit is provided in <flag> by the caller).
850 */
851int ssl_sock_handshake(struct connection *conn, unsigned int flag)
852{
853 int ret;
854
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200855 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200856 goto out_error;
857
Emeric Brun674b7432012-11-08 19:21:55 +0100858 /* If we use SSL_do_handshake to process a reneg initiated by
859 * the remote peer, it sometimes returns SSL_ERROR_SSL.
860 * Usually SSL_write and SSL_read are used and process implicitly
861 * the reneg handshake.
862 * Here we use SSL_peek as a workaround for reneg.
863 */
864 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
865 char c;
866
867 ret = SSL_peek(conn->xprt_ctx, &c, 1);
868 if (ret <= 0) {
869 /* handshake may have not been completed, let's find why */
870 ret = SSL_get_error(conn->xprt_ctx, ret);
871 if (ret == SSL_ERROR_WANT_WRITE) {
872 /* SSL handshake needs to write, L4 connection may not be ready */
873 __conn_sock_stop_recv(conn);
874 __conn_sock_poll_send(conn);
875 return 0;
876 }
877 else if (ret == SSL_ERROR_WANT_READ) {
878 /* handshake may have been completed but we have
879 * no more data to read.
880 */
881 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
882 ret = 1;
883 goto reneg_ok;
884 }
885 /* SSL handshake needs to read, L4 connection is ready */
886 if (conn->flags & CO_FL_WAIT_L4_CONN)
887 conn->flags &= ~CO_FL_WAIT_L4_CONN;
888 __conn_sock_stop_send(conn);
889 __conn_sock_poll_recv(conn);
890 return 0;
891 }
892 else if (ret == SSL_ERROR_SYSCALL) {
893 /* if errno is null, then connection was successfully established */
894 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
895 conn->flags &= ~CO_FL_WAIT_L4_CONN;
896 goto out_error;
897 }
898 else {
899 /* Fail on all other handshake errors */
900 /* Note: OpenSSL may leave unread bytes in the socket's
901 * buffer, causing an RST to be emitted upon close() on
902 * TCP sockets. We first try to drain possibly pending
903 * data to avoid this as much as possible.
904 */
905 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
906 goto out_error;
907 }
908 }
909 /* read some data: consider handshake completed */
910 goto reneg_ok;
911 }
912
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200913 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200914 if (ret != 1) {
915 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200916 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +0200917
918 if (ret == SSL_ERROR_WANT_WRITE) {
919 /* SSL handshake needs to write, L4 connection may not be ready */
920 __conn_sock_stop_recv(conn);
921 __conn_sock_poll_send(conn);
922 return 0;
923 }
924 else if (ret == SSL_ERROR_WANT_READ) {
925 /* SSL handshake needs to read, L4 connection is ready */
926 if (conn->flags & CO_FL_WAIT_L4_CONN)
927 conn->flags &= ~CO_FL_WAIT_L4_CONN;
928 __conn_sock_stop_send(conn);
929 __conn_sock_poll_recv(conn);
930 return 0;
931 }
Willy Tarreau89230192012-09-28 20:22:13 +0200932 else if (ret == SSL_ERROR_SYSCALL) {
933 /* if errno is null, then connection was successfully established */
934 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
935 conn->flags &= ~CO_FL_WAIT_L4_CONN;
936 goto out_error;
937 }
Emeric Brun46591952012-05-18 15:47:34 +0200938 else {
939 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +0200940 /* Note: OpenSSL may leave unread bytes in the socket's
941 * buffer, causing an RST to be emitted upon close() on
942 * TCP sockets. We first try to drain possibly pending
943 * data to avoid this as much as possible.
944 */
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100945 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Emeric Brun46591952012-05-18 15:47:34 +0200946 goto out_error;
947 }
948 }
949
Emeric Brun674b7432012-11-08 19:21:55 +0100950reneg_ok:
951
Emeric Brun46591952012-05-18 15:47:34 +0200952 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100953 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200954 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +0200955 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100956 if (objt_server(conn->target)->ssl_ctx.reused_sess)
957 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +0200958
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100959 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200960 }
961 }
962
963 /* The connection is now established at both layers, it's time to leave */
964 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
965 return 1;
966
967 out_error:
Emeric Brun9fa89732012-10-04 17:09:56 +0200968 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100969 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
970 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
971 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +0200972 }
973
Emeric Brun46591952012-05-18 15:47:34 +0200974 /* Fail on all other handshake errors */
975 conn->flags |= CO_FL_ERROR;
976 conn->flags &= ~flag;
977 return 0;
978}
979
980/* Receive up to <count> bytes from connection <conn>'s socket and store them
981 * into buffer <buf>. The caller must ensure that <count> is always smaller
982 * than the buffer's size. Only one call to recv() is performed, unless the
983 * buffer wraps, in which case a second call may be performed. The connection's
984 * flags are updated with whatever special event is detected (error, read0,
985 * empty). The caller is responsible for taking care of those events and
986 * avoiding the call if inappropriate. The function does not call the
987 * connection's polling update function, so the caller is responsible for this.
988 */
989static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
990{
991 int ret, done = 0;
992 int try = count;
993
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200994 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200995 goto out_error;
996
997 if (conn->flags & CO_FL_HANDSHAKE)
998 /* a handshake was requested */
999 return 0;
1000
1001 /* compute the maximum block size we can read at once. */
1002 if (buffer_empty(buf)) {
1003 /* let's realign the buffer to optimize I/O */
1004 buf->p = buf->data;
1005 }
1006 else if (buf->data + buf->o < buf->p &&
1007 buf->p + buf->i < buf->data + buf->size) {
1008 /* remaining space wraps at the end, with a moving limit */
1009 if (try > buf->data + buf->size - (buf->p + buf->i))
1010 try = buf->data + buf->size - (buf->p + buf->i);
1011 }
1012
1013 /* read the largest possible block. For this, we perform only one call
1014 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1015 * in which case we accept to do it once again. A new attempt is made on
1016 * EINTR too.
1017 */
1018 while (try) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001019 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001020 if (conn->flags & CO_FL_ERROR) {
1021 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
1022 break;
1023 }
Emeric Brun46591952012-05-18 15:47:34 +02001024 if (ret > 0) {
1025 buf->i += ret;
1026 done += ret;
1027 if (ret < try)
1028 break;
1029 count -= ret;
1030 try = count;
1031 }
1032 else if (ret == 0) {
1033 goto read0;
1034 }
1035 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001036 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001037 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001038 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001039 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001040 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001041 break;
1042 }
1043 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001044 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1045 /* handshake is running, and it may need to re-enable read */
1046 conn->flags |= CO_FL_SSL_WAIT_HS;
1047 __conn_sock_want_recv(conn);
1048 break;
1049 }
Emeric Brun46591952012-05-18 15:47:34 +02001050 /* we need to poll for retry a read later */
1051 __conn_data_poll_recv(conn);
1052 break;
1053 }
1054 /* otherwise it's a real error */
1055 goto out_error;
1056 }
1057 }
1058 return done;
1059
1060 read0:
1061 conn_sock_read0(conn);
1062 return done;
1063 out_error:
1064 conn->flags |= CO_FL_ERROR;
1065 return done;
1066}
1067
1068
1069/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1070 * <flags> may contain MSG_MORE to make the system hold on without sending
1071 * data too fast, but this flag is ignored at the moment.
1072 * Only one call to send() is performed, unless the buffer wraps, in which case
1073 * a second call may be performed. The connection's flags are updated with
1074 * whatever special event is detected (error, empty). The caller is responsible
1075 * for taking care of those events and avoiding the call if inappropriate. The
1076 * function does not call the connection's polling update function, so the caller
1077 * is responsible for this.
1078 */
1079static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1080{
1081 int ret, try, done;
1082
1083 done = 0;
1084
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001085 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001086 goto out_error;
1087
1088 if (conn->flags & CO_FL_HANDSHAKE)
1089 /* a handshake was requested */
1090 return 0;
1091
1092 /* send the largest possible block. For this we perform only one call
1093 * to send() unless the buffer wraps and we exactly fill the first hunk,
1094 * in which case we accept to do it once again.
1095 */
1096 while (buf->o) {
1097 try = buf->o;
1098 /* outgoing data may wrap at the end */
1099 if (buf->data + try > buf->p)
1100 try = buf->data + try - buf->p;
1101
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001102 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001103 if (conn->flags & CO_FL_ERROR) {
1104 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
1105 break;
1106 }
Emeric Brun46591952012-05-18 15:47:34 +02001107 if (ret > 0) {
1108 buf->o -= ret;
1109 done += ret;
1110
1111 if (likely(!buffer_len(buf)))
1112 /* optimize data alignment in the buffer */
1113 buf->p = buf->data;
1114
1115 /* if the system buffer is full, don't insist */
1116 if (ret < try)
1117 break;
1118 }
1119 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001120 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001121 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001122 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1123 /* handshake is running, and it may need to re-enable write */
1124 conn->flags |= CO_FL_SSL_WAIT_HS;
1125 __conn_sock_want_send(conn);
1126 break;
1127 }
Emeric Brun46591952012-05-18 15:47:34 +02001128 /* we need to poll to retry a write later */
1129 __conn_data_poll_send(conn);
1130 break;
1131 }
1132 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001133 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001134 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001135 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001136 break;
1137 }
1138 goto out_error;
1139 }
1140 }
1141 return done;
1142
1143 out_error:
1144 conn->flags |= CO_FL_ERROR;
1145 return done;
1146}
1147
1148
1149static void ssl_sock_close(struct connection *conn) {
1150
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001151 if (conn->xprt_ctx) {
1152 SSL_free(conn->xprt_ctx);
1153 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001154 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001155 }
Emeric Brun46591952012-05-18 15:47:34 +02001156}
1157
1158/* This function tries to perform a clean shutdown on an SSL connection, and in
1159 * any case, flags the connection as reusable if no handshake was in progress.
1160 */
1161static void ssl_sock_shutw(struct connection *conn, int clean)
1162{
1163 if (conn->flags & CO_FL_HANDSHAKE)
1164 return;
1165 /* no handshake was in progress, try a clean ssl shutdown */
1166 if (clean)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001167 SSL_shutdown(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001168
1169 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001170 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001171}
1172
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001173/* used for logging, may be changed for a sample fetch later */
1174const char *ssl_sock_get_cipher_name(struct connection *conn)
1175{
1176 if (!conn->xprt && !conn->xprt_ctx)
1177 return NULL;
1178 return SSL_get_cipher_name(conn->xprt_ctx);
1179}
1180
1181/* used for logging, may be changed for a sample fetch later */
1182const char *ssl_sock_get_proto_version(struct connection *conn)
1183{
1184 if (!conn->xprt && !conn->xprt_ctx)
1185 return NULL;
1186 return SSL_get_version(conn->xprt_ctx);
1187}
1188
Willy Tarreau8d598402012-10-22 17:58:39 +02001189/* Extract a serial from a cert, and copy it to a chunk.
1190 * Returns 1 if serial is found and copied, 0 if no serial found and
1191 * -1 if output is not large enough.
1192 */
1193static int
1194ssl_sock_get_serial(X509 *crt, struct chunk *out)
1195{
1196 ASN1_INTEGER *serial;
1197
1198 serial = X509_get_serialNumber(crt);
1199 if (!serial)
1200 return 0;
1201
1202 if (out->size < serial->length)
1203 return -1;
1204
1205 memcpy(out->str, serial->data, serial->length);
1206 out->len = serial->length;
1207 return 1;
1208}
1209
Emeric Brunce5ad802012-10-22 14:11:22 +02001210
1211/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1212 * Returns 1 if serial is found and copied, 0 if no valid time found
1213 * and -1 if output is not large enough.
1214 */
1215static int
1216ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1217{
1218 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1219 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1220
1221 if (gentm->length < 12)
1222 return 0;
1223 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1224 return 0;
1225 if (out->size < gentm->length-2)
1226 return -1;
1227
1228 memcpy(out->str, gentm->data+2, gentm->length-2);
1229 out->len = gentm->length-2;
1230 return 1;
1231 }
1232 else if (tm->type == V_ASN1_UTCTIME) {
1233 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1234
1235 if (utctm->length < 10)
1236 return 0;
1237 if (utctm->data[0] >= 0x35)
1238 return 0;
1239 if (out->size < utctm->length)
1240 return -1;
1241
1242 memcpy(out->str, utctm->data, utctm->length);
1243 out->len = utctm->length;
1244 return 1;
1245 }
1246
1247 return 0;
1248}
1249
Emeric Brun87855892012-10-17 17:39:35 +02001250/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1251 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1252 */
1253static int
1254ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1255{
1256 X509_NAME_ENTRY *ne;
1257 int i, j, n;
1258 int cur = 0;
1259 const char *s;
1260 char tmp[128];
1261
1262 out->len = 0;
1263 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1264 if (pos < 0)
1265 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1266 else
1267 j = i;
1268
1269 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1270 n = OBJ_obj2nid(ne->object);
1271 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1272 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1273 s = tmp;
1274 }
1275
1276 if (chunk_strcasecmp(entry, s) != 0)
1277 continue;
1278
1279 if (pos < 0)
1280 cur--;
1281 else
1282 cur++;
1283
1284 if (cur != pos)
1285 continue;
1286
1287 if (ne->value->length > out->size)
1288 return -1;
1289
1290 memcpy(out->str, ne->value->data, ne->value->length);
1291 out->len = ne->value->length;
1292 return 1;
1293 }
1294
1295 return 0;
1296
1297}
1298
1299/* Extract and format full DN from a X509_NAME and copy result into a chunk
1300 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1301 */
1302static int
1303ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1304{
1305 X509_NAME_ENTRY *ne;
1306 int i, n, ln;
1307 int l = 0;
1308 const char *s;
1309 char *p;
1310 char tmp[128];
1311
1312 out->len = 0;
1313 p = out->str;
1314 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1315 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1316 n = OBJ_obj2nid(ne->object);
1317 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1318 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1319 s = tmp;
1320 }
1321 ln = strlen(s);
1322
1323 l += 1 + ln + 1 + ne->value->length;
1324 if (l > out->size)
1325 return -1;
1326 out->len = l;
1327
1328 *(p++)='/';
1329 memcpy(p, s, ln);
1330 p += ln;
1331 *(p++)='=';
1332 memcpy(p, ne->value->data, ne->value->length);
1333 p += ne->value->length;
1334 }
1335
1336 if (!out->len)
1337 return 0;
1338
1339 return 1;
1340}
1341
Willy Tarreau7875d092012-09-10 08:20:03 +02001342/***** Below are some sample fetching functions for ACL/patterns *****/
1343
Emeric Brune64aef12012-09-21 13:15:06 +02001344/* boolean, returns true if client cert was present */
1345static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001346smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1347 const struct arg *args, struct sample *smp)
Emeric Brune64aef12012-09-21 13:15:06 +02001348{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001349 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001350 return 0;
1351
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001352 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001353 smp->flags |= SMP_F_MAY_CHANGE;
1354 return 0;
1355 }
1356
1357 smp->flags = 0;
1358 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001359 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001360
1361 return 1;
1362}
1363
Willy Tarreau8d598402012-10-22 17:58:39 +02001364/* bin, returns serial in a binary chunk */
1365static int
1366smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1367 const struct arg *args, struct sample *smp)
1368{
1369 X509 *crt = NULL;
1370 int ret = 0;
1371 struct chunk *smp_trash;
1372
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001373 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001374 return 0;
1375
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001376 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001377 smp->flags |= SMP_F_MAY_CHANGE;
1378 return 0;
1379 }
1380
1381 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001382 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001383 if (!crt)
1384 goto out;
1385
1386 smp_trash = sample_get_trash_chunk();
1387 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1388 goto out;
1389
1390 smp->data.str = *smp_trash;
1391 smp->type = SMP_T_BIN;
1392 ret = 1;
1393out:
1394 if (crt)
1395 X509_free(crt);
1396 return ret;
1397}
Emeric Brune64aef12012-09-21 13:15:06 +02001398
Emeric Brunce5ad802012-10-22 14:11:22 +02001399/*str, returns notafter date in ASN1_UTCTIME format */
1400static int
1401smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1402 const struct arg *args, struct sample *smp)
1403{
1404 X509 *crt = NULL;
1405 int ret = 0;
1406 struct chunk *smp_trash;
1407
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001408 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001409 return 0;
1410
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001411 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001412 smp->flags |= SMP_F_MAY_CHANGE;
1413 return 0;
1414 }
1415
1416 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001417 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001418 if (!crt)
1419 goto out;
1420
1421 smp_trash = sample_get_trash_chunk();
1422 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1423 goto out;
1424
1425 smp->data.str = *smp_trash;
1426 smp->type = SMP_T_STR;
1427 ret = 1;
1428out:
1429 if (crt)
1430 X509_free(crt);
1431 return ret;
1432}
1433
Emeric Brun87855892012-10-17 17:39:35 +02001434/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1435static int
1436smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1437 const struct arg *args, struct sample *smp)
1438{
1439 X509 *crt = NULL;
1440 X509_NAME *name;
1441 int ret = 0;
1442 struct chunk *smp_trash;
1443
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001444 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001445 return 0;
1446
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001447 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001448 smp->flags |= SMP_F_MAY_CHANGE;
1449 return 0;
1450 }
1451
1452 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001453 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001454 if (!crt)
1455 goto out;
1456
1457 name = X509_get_issuer_name(crt);
1458 if (!name)
1459 goto out;
1460
1461 smp_trash = sample_get_trash_chunk();
1462 if (args && args[0].type == ARGT_STR) {
1463 int pos = 1;
1464
1465 if (args[1].type == ARGT_SINT)
1466 pos = args[1].data.sint;
1467 else if (args[1].type == ARGT_UINT)
1468 pos =(int)args[1].data.uint;
1469
1470 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1471 goto out;
1472 }
1473 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1474 goto out;
1475
1476 smp->type = SMP_T_STR;
1477 smp->data.str = *smp_trash;
1478 ret = 1;
1479out:
1480 if (crt)
1481 X509_free(crt);
1482 return ret;
1483}
1484
Emeric Brunce5ad802012-10-22 14:11:22 +02001485/*str, returns notbefore date in ASN1_UTCTIME format */
1486static int
1487smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1488 const struct arg *args, struct sample *smp)
1489{
1490 X509 *crt = NULL;
1491 int ret = 0;
1492 struct chunk *smp_trash;
1493
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001494 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001495 return 0;
1496
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001497 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001498 smp->flags |= SMP_F_MAY_CHANGE;
1499 return 0;
1500 }
1501
1502 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001503 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001504 if (!crt)
1505 goto out;
1506
1507 smp_trash = sample_get_trash_chunk();
1508 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1509 goto out;
1510
1511 smp->data.str = *smp_trash;
1512 smp->type = SMP_T_STR;
1513 ret = 1;
1514out:
1515 if (crt)
1516 X509_free(crt);
1517 return ret;
1518}
1519
Emeric Brun87855892012-10-17 17:39:35 +02001520/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1521static int
1522smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1523 const struct arg *args, struct sample *smp)
1524{
1525 X509 *crt = NULL;
1526 X509_NAME *name;
1527 int ret = 0;
1528 struct chunk *smp_trash;
1529
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001530 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001531 return 0;
1532
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001533 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001534 smp->flags |= SMP_F_MAY_CHANGE;
1535 return 0;
1536 }
1537
1538 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001539 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001540 if (!crt)
1541 goto out;
1542
1543 name = X509_get_subject_name(crt);
1544 if (!name)
1545 goto out;
1546
1547 smp_trash = sample_get_trash_chunk();
1548 if (args && args[0].type == ARGT_STR) {
1549 int pos = 1;
1550
1551 if (args[1].type == ARGT_SINT)
1552 pos = args[1].data.sint;
1553 else if (args[1].type == ARGT_UINT)
1554 pos =(int)args[1].data.uint;
1555
1556 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1557 goto out;
1558 }
1559 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1560 goto out;
1561
1562 smp->type = SMP_T_STR;
1563 smp->data.str = *smp_trash;
1564 ret = 1;
1565out:
1566 if (crt)
1567 X509_free(crt);
1568 return ret;
1569}
Emeric Bruna7359fd2012-10-17 15:03:11 +02001570/* integer, returns the client certificate version */
1571static int
1572smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1573 const struct arg *args, struct sample *smp)
1574{
1575 X509 *crt;
1576
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001577 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001578 return 0;
1579
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001580 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001581 smp->flags |= SMP_F_MAY_CHANGE;
1582 return 0;
1583 }
1584
1585 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001586 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001587 if (!crt)
1588 return 0;
1589
1590 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1591 X509_free(crt);
1592 smp->type = SMP_T_UINT;
1593
1594 return 1;
1595}
1596
Emeric Brun7f56e742012-10-19 18:15:40 +02001597/* str, returns the client certificate sig alg */
1598static int
1599smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1600 const struct arg *args, struct sample *smp)
1601{
1602 X509 *crt;
1603 int nid;
1604
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001605 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02001606 return 0;
1607
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001608 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02001609 smp->flags |= SMP_F_MAY_CHANGE;
1610 return 0;
1611 }
1612
1613 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001614 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02001615 if (!crt)
1616 return 0;
1617
1618 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1619
1620 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1621 if (!smp->data.str.str)
1622 return 0;
1623
1624 smp->type = SMP_T_CSTR;
1625 smp->data.str.len = strlen(smp->data.str.str);
1626 X509_free(crt);
1627
1628 return 1;
1629}
1630
Emeric Brun521a0112012-10-22 12:22:55 +02001631/* str, returns the client certificate key alg */
1632static int
1633smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1634 const struct arg *args, struct sample *smp)
1635{
1636 X509 *crt;
1637 int nid;
1638
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001639 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02001640 return 0;
1641
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001642 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02001643 smp->flags |= SMP_F_MAY_CHANGE;
1644 return 0;
1645 }
1646
1647 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001648 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02001649 if (!crt)
1650 return 0;
1651
1652 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1653
1654 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1655 if (!smp->data.str.str)
1656 return 0;
1657
1658 smp->type = SMP_T_CSTR;
1659 smp->data.str.len = strlen(smp->data.str.str);
1660 X509_free(crt);
1661
1662 return 1;
1663}
1664
Emeric Brun2525b6b2012-10-18 15:59:43 +02001665/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02001666static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001667smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau7875d092012-09-10 08:20:03 +02001668 const struct arg *args, struct sample *smp)
1669{
1670 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001671 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02001672 return 1;
1673}
1674
Emeric Brun2525b6b2012-10-18 15:59:43 +02001675/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02001676static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001677smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1678 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02001679{
1680#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1681 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001682 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock) &&
1683 l4->si[0].conn->xprt_ctx &&
1684 SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02001685 return 1;
1686#else
1687 return 0;
1688#endif
1689}
1690
Willy Tarreau8d598402012-10-22 17:58:39 +02001691/* bin, returns serial in a binary chunk */
1692static int
1693smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1694 const struct arg *args, struct sample *smp)
1695{
1696 X509 *crt = NULL;
1697 int ret = 0;
1698 struct chunk *smp_trash;
1699
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001700 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001701 return 0;
1702
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001703 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001704 smp->flags |= SMP_F_MAY_CHANGE;
1705 return 0;
1706 }
1707
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001708 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001709 if (!crt)
1710 goto out;
1711
1712 smp_trash = sample_get_trash_chunk();
1713 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1714 goto out;
1715
1716 smp->data.str = *smp_trash;
1717 smp->type = SMP_T_BIN;
1718 ret = 1;
1719out:
1720 return ret;
1721}
Emeric Brunce5ad802012-10-22 14:11:22 +02001722/*str, returns notafter date in ASN1_UTCTIME format */
1723static int
1724smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1725 const struct arg *args, struct sample *smp)
1726{
1727 X509 *crt = NULL;
1728 int ret = 0;
1729 struct chunk *smp_trash;
1730
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001731 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001732 return 0;
1733
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001734 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001735 smp->flags |= SMP_F_MAY_CHANGE;
1736 return 0;
1737 }
1738
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001739 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001740 if (!crt)
1741 goto out;
1742
1743 smp_trash = sample_get_trash_chunk();
1744 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1745 goto out;
1746
1747 smp->data.str = *smp_trash;
1748 smp->type = SMP_T_STR;
1749 ret = 1;
1750out:
1751 return ret;
1752}
1753
1754/*str, returns notbefore date in ASN1_UTCTIME format */
1755static int
1756smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1757 const struct arg *args, struct sample *smp)
1758{
1759 X509 *crt = NULL;
1760 int ret = 0;
1761 struct chunk *smp_trash;
1762
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001763 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001764 return 0;
1765
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001766 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001767 smp->flags |= SMP_F_MAY_CHANGE;
1768 return 0;
1769 }
1770
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001771 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001772 if (!crt)
1773 goto out;
1774
1775 smp_trash = sample_get_trash_chunk();
1776 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1777 goto out;
1778
1779 smp->data.str = *smp_trash;
1780 smp->type = SMP_T_STR;
1781 ret = 1;
1782out:
1783 return ret;
1784}
Willy Tarreau8d598402012-10-22 17:58:39 +02001785
Emeric Bruna7359fd2012-10-17 15:03:11 +02001786/* integer, returns the frontend certificate version */
1787static int
1788smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1789 const struct arg *args, struct sample *smp)
1790{
1791 X509 *crt;
1792
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001793 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001794 return 0;
1795
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001796 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001797 smp->flags |= SMP_F_MAY_CHANGE;
1798 return 0;
1799 }
1800
1801 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001802 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001803 if (!crt)
1804 return 0;
1805
1806 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1807 smp->type = SMP_T_UINT;
1808
1809 return 1;
1810}
1811
Emeric Brun7f56e742012-10-19 18:15:40 +02001812/* str, returns the client certificate sig alg */
1813static int
1814smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1815 const struct arg *args, struct sample *smp)
1816{
1817 X509 *crt;
1818 int nid;
1819
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001820 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02001821 return 0;
1822
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001823 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02001824 smp->flags |= SMP_F_MAY_CHANGE;
1825 return 0;
1826 }
1827
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001828 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02001829 if (!crt)
1830 return 0;
1831
1832 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1833
1834 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1835 if (!smp->data.str.str)
1836 return 0;
1837
1838 smp->type = SMP_T_CSTR;
1839 smp->data.str.len = strlen(smp->data.str.str);
1840
1841 return 1;
1842}
1843
Emeric Brun521a0112012-10-22 12:22:55 +02001844/* str, returns the client certificate key alg */
1845static int
1846smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1847 const struct arg *args, struct sample *smp)
1848{
1849 X509 *crt;
1850 int nid;
1851
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001852 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02001853 return 0;
1854
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001855 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02001856 smp->flags |= SMP_F_MAY_CHANGE;
1857 return 0;
1858 }
1859
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001860 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02001861 if (!crt)
1862 return 0;
1863
1864 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1865
1866 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1867 if (!smp->data.str.str)
1868 return 0;
1869
1870 smp->type = SMP_T_CSTR;
1871 smp->data.str.len = strlen(smp->data.str.str);
1872
1873 return 1;
1874}
1875
Emeric Brun87855892012-10-17 17:39:35 +02001876/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1877static int
1878smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1879 const struct arg *args, struct sample *smp)
1880{
1881 X509 *crt = NULL;
1882 X509_NAME *name;
1883 int ret = 0;
1884 struct chunk *smp_trash;
1885
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001886 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001887 return 0;
1888
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001889 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001890 smp->flags |= SMP_F_MAY_CHANGE;
1891 return 0;
1892 }
1893
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001894 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001895 if (!crt)
1896 goto out;
1897
1898 name = X509_get_issuer_name(crt);
1899 if (!name)
1900 goto out;
1901
1902 smp_trash = sample_get_trash_chunk();
1903 if (args && args[0].type == ARGT_STR) {
1904 int pos = 1;
1905
1906 if (args[1].type == ARGT_SINT)
1907 pos = args[1].data.sint;
1908 else if (args[1].type == ARGT_UINT)
1909 pos =(int)args[1].data.uint;
1910
1911 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1912 goto out;
1913 }
1914 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1915 goto out;
1916
1917 smp->type = SMP_T_STR;
1918 smp->data.str = *smp_trash;
1919 ret = 1;
1920out:
1921 return ret;
1922}
1923
1924/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1925static int
1926smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1927 const struct arg *args, struct sample *smp)
1928{
1929 X509 *crt = NULL;
1930 X509_NAME *name;
1931 int ret = 0;
1932 struct chunk *smp_trash;
1933
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001934 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001935 return 0;
1936
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001937 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001938 smp->flags |= SMP_F_MAY_CHANGE;
1939 return 0;
1940 }
1941
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001942 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001943 if (!crt)
1944 goto out;
1945
1946 name = X509_get_subject_name(crt);
1947 if (!name)
1948 goto out;
1949
1950 smp_trash = sample_get_trash_chunk();
1951 if (args && args[0].type == ARGT_STR) {
1952 int pos = 1;
1953
1954 if (args[1].type == ARGT_SINT)
1955 pos = args[1].data.sint;
1956 else if (args[1].type == ARGT_UINT)
1957 pos =(int)args[1].data.uint;
1958
1959 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1960 goto out;
1961 }
1962 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1963 goto out;
1964
1965 smp->type = SMP_T_STR;
1966 smp->data.str = *smp_trash;
1967 ret = 1;
1968out:
1969 return ret;
1970}
1971
Emeric Brun589fcad2012-10-16 14:13:26 +02001972static int
1973smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1974 const struct arg *args, struct sample *smp)
1975{
1976 smp->flags = 0;
1977
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001978 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02001979 return 0;
1980
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001981 smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02001982 if (!smp->data.str.str)
1983 return 0;
1984
1985 smp->type = SMP_T_CSTR;
1986 smp->data.str.len = strlen(smp->data.str.str);
1987
1988 return 1;
1989}
1990
1991static int
1992smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1993 const struct arg *args, struct sample *smp)
1994{
1995 smp->flags = 0;
1996
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001997 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02001998 return 0;
1999
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002000 if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
Emeric Brun589fcad2012-10-16 14:13:26 +02002001 return 0;
2002
2003 smp->type = SMP_T_UINT;
2004
2005 return 1;
2006}
2007
2008static int
2009smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2010 const struct arg *args, struct sample *smp)
2011{
2012 smp->flags = 0;
2013
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002014 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002015 return 0;
2016
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002017 smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002018 if (!smp->data.uint)
2019 return 0;
2020
2021 smp->type = SMP_T_UINT;
2022
2023 return 1;
2024}
2025
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002026#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002027static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002028smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2029 const struct arg *args, struct sample *smp)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002030{
Willy Tarreaua33c6542012-10-15 13:19:06 +02002031 smp->flags = 0;
2032 smp->type = SMP_T_CSTR;
2033
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002034 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002035 return 0;
2036
2037 smp->data.str.str = NULL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002038 SSL_get0_next_proto_negotiated(l4->si[0].conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002039 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2040
2041 if (!smp->data.str.str)
2042 return 0;
2043
2044 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002045}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002046#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002047
2048static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002049smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2050 const struct arg *args, struct sample *smp)
2051{
2052 smp->flags = 0;
2053
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002054 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002055 return 0;
2056
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002057 smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002058 if (!smp->data.str.str)
2059 return 0;
2060
2061 smp->type = SMP_T_CSTR;
2062 smp->data.str.len = strlen(smp->data.str.str);
2063
2064 return 1;
2065}
2066
2067static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002068smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2069 const struct arg *args, struct sample *smp)
2070{
2071#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2072 SSL_SESSION *sess;
2073
2074 smp->flags = 0;
2075 smp->type = SMP_T_CBIN;
2076
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002077 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunfe68f682012-10-16 14:59:28 +02002078 return 0;
2079
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002080 sess = SSL_get_session(l4->si[0].conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002081 if (!sess)
2082 return 0;
2083
2084 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2085 if (!smp->data.str.str || !&smp->data.str.len)
2086 return 0;
2087
2088 return 1;
2089#else
2090 return 0;
2091#endif
2092}
2093
2094static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002095smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2096 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02002097{
2098#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2099 smp->flags = 0;
2100 smp->type = SMP_T_CSTR;
2101
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002102 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau7875d092012-09-10 08:20:03 +02002103 return 0;
2104
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002105 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 +02002106 if (!smp->data.str.str)
2107 return 0;
2108
Willy Tarreau7875d092012-09-10 08:20:03 +02002109 smp->data.str.len = strlen(smp->data.str.str);
2110 return 1;
2111#else
2112 return 0;
2113#endif
2114}
2115
Emeric Brun2525b6b2012-10-18 15:59:43 +02002116/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002117static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002118smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002119 const struct arg *args, struct sample *smp)
2120{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002121 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002122 return 0;
2123
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002124 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002125 smp->flags = SMP_F_MAY_CHANGE;
2126 return 0;
2127 }
2128
2129 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002130 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002131 smp->flags = 0;
2132
2133 return 1;
2134}
2135
Emeric Brun2525b6b2012-10-18 15:59:43 +02002136/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002137static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002138smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002139 const struct arg *args, struct sample *smp)
2140{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002141 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002142 return 0;
2143
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002144 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002145 smp->flags = SMP_F_MAY_CHANGE;
2146 return 0;
2147 }
2148
2149 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002150 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002151 smp->flags = 0;
2152
2153 return 1;
2154}
2155
Emeric Brun2525b6b2012-10-18 15:59:43 +02002156/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002157static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002158smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2159 const struct arg *args, struct sample *smp)
Emeric Brunf282a812012-09-21 15:27:54 +02002160{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002161 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002162 return 0;
2163
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002164 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002165 smp->flags = SMP_F_MAY_CHANGE;
2166 return 0;
2167 }
2168
2169 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002170 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002171 smp->flags = 0;
2172
2173 return 1;
2174}
2175
Emeric Brun2525b6b2012-10-18 15:59:43 +02002176/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002177static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002178smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2179 const struct arg *args, struct sample *smp)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002180{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002181 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002182 return 0;
2183
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002184 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002185 smp->flags = SMP_F_MAY_CHANGE;
2186 return 0;
2187 }
2188
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002189 if (!l4->si[0].conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002190 return 0;
2191
2192 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002193 smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002194 smp->flags = 0;
2195
2196 return 1;
2197}
2198
Emeric Brunfb510ea2012-10-05 12:00:26 +02002199/* parse the "ca-file" bind keyword */
2200static 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 +02002201{
2202 if (!*args[cur_arg + 1]) {
2203 if (err)
2204 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2205 return ERR_ALERT | ERR_FATAL;
2206 }
2207
Emeric Brunef42d922012-10-11 16:11:36 +02002208 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2209 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2210 else
2211 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002212
Emeric Brund94b3fe2012-09-20 18:23:56 +02002213 return 0;
2214}
2215
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002216/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002217static 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 +02002218{
2219 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002220 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002221 return ERR_ALERT | ERR_FATAL;
2222 }
2223
Emeric Brun76d88952012-10-05 15:47:31 +02002224 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002225 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002226 return 0;
2227}
2228
2229/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002230static 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 +02002231{
Emeric Brunc8e8d122012-10-02 18:42:10 +02002232 char path[PATH_MAX];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002233 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002234 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002235 return ERR_ALERT | ERR_FATAL;
2236 }
2237
Emeric Brunc8e8d122012-10-02 18:42:10 +02002238 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
2239 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > PATH_MAX) {
2240 memprintf(err, "'%s' : path too long", args[cur_arg]);
2241 return ERR_ALERT | ERR_FATAL;
2242 }
2243 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2244 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2245 return ERR_ALERT | ERR_FATAL;
2246
2247 return 0;
2248 }
2249
Willy Tarreau4348fad2012-09-20 16:48:07 +02002250 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002251 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002252
2253 return 0;
2254}
2255
Emeric Brunfb510ea2012-10-05 12:00:26 +02002256/* parse the "crl-file" bind keyword */
2257static 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 +02002258{
Emeric Brun051cdab2012-10-02 19:25:50 +02002259#ifndef X509_V_FLAG_CRL_CHECK
2260 if (err)
2261 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2262 return ERR_ALERT | ERR_FATAL;
2263#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002264 if (!*args[cur_arg + 1]) {
2265 if (err)
2266 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2267 return ERR_ALERT | ERR_FATAL;
2268 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002269
Emeric Brunef42d922012-10-11 16:11:36 +02002270 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2271 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2272 else
2273 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002274
Emeric Brun2b58d042012-09-20 17:10:03 +02002275 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002276#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002277}
2278
2279/* parse the "ecdhe" bind keyword keywords */
2280static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2281{
2282#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2283 if (err)
2284 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2285 return ERR_ALERT | ERR_FATAL;
2286#elif defined(OPENSSL_NO_ECDH)
2287 if (err)
2288 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2289 return ERR_ALERT | ERR_FATAL;
2290#else
2291 if (!*args[cur_arg + 1]) {
2292 if (err)
2293 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2294 return ERR_ALERT | ERR_FATAL;
2295 }
2296
2297 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002298
2299 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002300#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002301}
2302
Emeric Brun81c00f02012-09-21 14:31:21 +02002303/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2304static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2305{
2306 int code;
2307 char *p = args[cur_arg + 1];
2308 unsigned long long *ignerr = &conf->crt_ignerr;
2309
2310 if (!*p) {
2311 if (err)
2312 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2313 return ERR_ALERT | ERR_FATAL;
2314 }
2315
2316 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2317 ignerr = &conf->ca_ignerr;
2318
2319 if (strcmp(p, "all") == 0) {
2320 *ignerr = ~0ULL;
2321 return 0;
2322 }
2323
2324 while (p) {
2325 code = atoi(p);
2326 if ((code <= 0) || (code > 63)) {
2327 if (err)
2328 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2329 args[cur_arg], code, args[cur_arg + 1]);
2330 return ERR_ALERT | ERR_FATAL;
2331 }
2332 *ignerr |= 1ULL << code;
2333 p = strchr(p, ',');
2334 if (p)
2335 p++;
2336 }
2337
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002338 return 0;
2339}
2340
2341/* parse the "force-sslv3" bind keyword */
2342static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2343{
2344 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2345 return 0;
2346}
2347
2348/* parse the "force-tlsv10" bind keyword */
2349static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2350{
2351 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002352 return 0;
2353}
2354
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002355/* parse the "force-tlsv11" bind keyword */
2356static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2357{
2358#if SSL_OP_NO_TLSv1_1
2359 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
2360 return 0;
2361#else
2362 if (err)
2363 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
2364 return ERR_ALERT | ERR_FATAL;
2365#endif
2366}
2367
2368/* parse the "force-tlsv12" bind keyword */
2369static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2370{
2371#if SSL_OP_NO_TLSv1_2
2372 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
2373 return 0;
2374#else
2375 if (err)
2376 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
2377 return ERR_ALERT | ERR_FATAL;
2378#endif
2379}
2380
2381
Emeric Brun2d0c4822012-10-02 13:45:20 +02002382/* parse the "no-tls-tickets" bind keyword */
2383static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2384{
Emeric Brun89675492012-10-05 13:48:26 +02002385 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02002386 return 0;
2387}
2388
Emeric Brun2d0c4822012-10-02 13:45:20 +02002389
Emeric Brun9b3009b2012-10-05 11:55:06 +02002390/* parse the "no-sslv3" bind keyword */
2391static 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 +02002392{
Emeric Brun89675492012-10-05 13:48:26 +02002393 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002394 return 0;
2395}
2396
Emeric Brun9b3009b2012-10-05 11:55:06 +02002397/* parse the "no-tlsv10" bind keyword */
2398static 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 +02002399{
Emeric Brun89675492012-10-05 13:48:26 +02002400 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002401 return 0;
2402}
2403
Emeric Brun9b3009b2012-10-05 11:55:06 +02002404/* parse the "no-tlsv11" bind keyword */
2405static 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 +02002406{
Emeric Brun89675492012-10-05 13:48:26 +02002407 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002408 return 0;
2409}
2410
Emeric Brun9b3009b2012-10-05 11:55:06 +02002411/* parse the "no-tlsv12" bind keyword */
2412static 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 +02002413{
Emeric Brun89675492012-10-05 13:48:26 +02002414 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002415 return 0;
2416}
2417
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002418/* parse the "npn" bind keyword */
2419static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2420{
2421#ifdef OPENSSL_NPN_NEGOTIATED
2422 char *p1, *p2;
2423
2424 if (!*args[cur_arg + 1]) {
2425 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
2426 return ERR_ALERT | ERR_FATAL;
2427 }
2428
2429 free(conf->npn_str);
2430
2431 /* the NPN string is built as a suite of (<len> <name>)* */
2432 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
2433 conf->npn_str = calloc(1, conf->npn_len);
2434 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
2435
2436 /* replace commas with the name length */
2437 p1 = conf->npn_str;
2438 p2 = p1 + 1;
2439 while (1) {
2440 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
2441 if (!p2)
2442 p2 = p1 + 1 + strlen(p1 + 1);
2443
2444 if (p2 - (p1 + 1) > 255) {
2445 *p2 = '\0';
2446 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2447 return ERR_ALERT | ERR_FATAL;
2448 }
2449
2450 *p1 = p2 - (p1 + 1);
2451 p1 = p2;
2452
2453 if (!*p2)
2454 break;
2455
2456 *(p2++) = '\0';
2457 }
2458 return 0;
2459#else
2460 if (err)
2461 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
2462 return ERR_ALERT | ERR_FATAL;
2463#endif
2464}
2465
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002466/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002467static 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 +02002468{
Willy Tarreau81796be2012-09-22 19:11:47 +02002469 struct listener *l;
2470
Willy Tarreau4348fad2012-09-20 16:48:07 +02002471 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02002472
2473 if (global.listen_default_ciphers && !conf->ciphers)
2474 conf->ciphers = strdup(global.listen_default_ciphers);
2475
Willy Tarreau81796be2012-09-22 19:11:47 +02002476 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002477 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02002478
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002479 return 0;
2480}
2481
Emeric Brund94b3fe2012-09-20 18:23:56 +02002482/* parse the "verify" bind keyword */
2483static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2484{
2485 if (!*args[cur_arg + 1]) {
2486 if (err)
2487 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
2488 return ERR_ALERT | ERR_FATAL;
2489 }
2490
2491 if (strcmp(args[cur_arg + 1], "none") == 0)
2492 conf->verify = SSL_VERIFY_NONE;
2493 else if (strcmp(args[cur_arg + 1], "optional") == 0)
2494 conf->verify = SSL_VERIFY_PEER;
2495 else if (strcmp(args[cur_arg + 1], "required") == 0)
2496 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2497 else {
2498 if (err)
2499 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
2500 args[cur_arg], args[cur_arg + 1]);
2501 return ERR_ALERT | ERR_FATAL;
2502 }
2503
2504 return 0;
2505}
2506
Willy Tarreau92faadf2012-10-10 23:04:25 +02002507/************** "server" keywords ****************/
2508
Emeric Brunef42d922012-10-11 16:11:36 +02002509/* parse the "ca-file" server keyword */
2510static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2511{
2512 if (!*args[*cur_arg + 1]) {
2513 if (err)
2514 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
2515 return ERR_ALERT | ERR_FATAL;
2516 }
2517
2518 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2519 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2520 else
2521 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
2522
2523 return 0;
2524}
2525
Willy Tarreau92faadf2012-10-10 23:04:25 +02002526/* parse the "check-ssl" server keyword */
2527static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2528{
2529 newsrv->check.use_ssl = 1;
2530 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2531 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2532 return 0;
2533}
2534
2535/* parse the "ciphers" server keyword */
2536static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2537{
2538 if (!*args[*cur_arg + 1]) {
2539 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
2540 return ERR_ALERT | ERR_FATAL;
2541 }
2542
2543 free(newsrv->ssl_ctx.ciphers);
2544 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
2545 return 0;
2546}
2547
Emeric Brunef42d922012-10-11 16:11:36 +02002548/* parse the "crl-file" server keyword */
2549static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2550{
2551#ifndef X509_V_FLAG_CRL_CHECK
2552 if (err)
2553 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
2554 return ERR_ALERT | ERR_FATAL;
2555#else
2556 if (!*args[*cur_arg + 1]) {
2557 if (err)
2558 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
2559 return ERR_ALERT | ERR_FATAL;
2560 }
2561
2562 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2563 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2564 else
2565 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
2566
2567 return 0;
2568#endif
2569}
2570
Emeric Bruna7aa3092012-10-26 12:58:00 +02002571/* parse the "crt" server keyword */
2572static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2573{
2574 if (!*args[*cur_arg + 1]) {
2575 if (err)
2576 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
2577 return ERR_ALERT | ERR_FATAL;
2578 }
2579
2580 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
2581 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2582 else
2583 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
2584
2585 return 0;
2586}
Emeric Brunef42d922012-10-11 16:11:36 +02002587
Willy Tarreau92faadf2012-10-10 23:04:25 +02002588/* parse the "force-sslv3" server keyword */
2589static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2590{
2591 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
2592 return 0;
2593}
2594
2595/* parse the "force-tlsv10" server keyword */
2596static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2597{
2598 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
2599 return 0;
2600}
2601
2602/* parse the "force-tlsv11" server keyword */
2603static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2604{
2605#if SSL_OP_NO_TLSv1_1
2606 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
2607 return 0;
2608#else
2609 if (err)
2610 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
2611 return ERR_ALERT | ERR_FATAL;
2612#endif
2613}
2614
2615/* parse the "force-tlsv12" server keyword */
2616static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2617{
2618#if SSL_OP_NO_TLSv1_2
2619 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
2620 return 0;
2621#else
2622 if (err)
2623 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
2624 return ERR_ALERT | ERR_FATAL;
2625#endif
2626}
2627
2628/* parse the "no-sslv3" server keyword */
2629static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2630{
2631 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
2632 return 0;
2633}
2634
2635/* parse the "no-tlsv10" server keyword */
2636static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2637{
2638 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
2639 return 0;
2640}
2641
2642/* parse the "no-tlsv11" server keyword */
2643static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2644{
2645 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
2646 return 0;
2647}
2648
2649/* parse the "no-tlsv12" server keyword */
2650static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2651{
2652 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
2653 return 0;
2654}
2655
Emeric Brunf9c5c472012-10-11 15:28:34 +02002656/* parse the "no-tls-tickets" server keyword */
2657static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2658{
2659 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
2660 return 0;
2661}
2662
Willy Tarreau92faadf2012-10-10 23:04:25 +02002663/* parse the "ssl" server keyword */
2664static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2665{
2666 newsrv->use_ssl = 1;
2667 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2668 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2669 return 0;
2670}
2671
Emeric Brunef42d922012-10-11 16:11:36 +02002672/* parse the "verify" server keyword */
2673static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2674{
2675 if (!*args[*cur_arg + 1]) {
2676 if (err)
2677 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
2678 return ERR_ALERT | ERR_FATAL;
2679 }
2680
2681 if (strcmp(args[*cur_arg + 1], "none") == 0)
2682 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
2683 else if (strcmp(args[*cur_arg + 1], "required") == 0)
2684 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
2685 else {
2686 if (err)
2687 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
2688 args[*cur_arg], args[*cur_arg + 1]);
2689 return ERR_ALERT | ERR_FATAL;
2690 }
2691
2692 return 0;
2693}
2694
Willy Tarreau7875d092012-09-10 08:20:03 +02002695/* Note: must not be declared <const> as its list will be overwritten.
2696 * Please take care of keeping this list alphabetically sorted.
2697 */
2698static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
Emeric Brun2525b6b2012-10-18 15:59:43 +02002699 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2700 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2701 { "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 +02002702 { "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 +02002703 { "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 +02002704 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
2705 { "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 +02002706 { "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 +02002707 { "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 +02002708 { "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 +02002709 { "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 +02002710 { "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 +02002711 { "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 +02002712 { "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 +02002713 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
2714 { "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 +02002715 { "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 +02002716 { "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 +02002717 { "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 +02002718 { "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 +02002719 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun589fcad2012-10-16 14:13:26 +02002720 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2721 { "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 +02002722 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
2723 { "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 +02002724#ifdef OPENSSL_NPN_NEGOTIATED
Emeric Brun2525b6b2012-10-18 15:59:43 +02002725 { "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 +02002726#endif
Emeric Brun589fcad2012-10-16 14:13:26 +02002727 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
2728 { "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 +02002729 { "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 +02002730 { "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 +02002731 { NULL, NULL, 0, 0, 0 },
2732}};
2733
2734/* Note: must not be declared <const> as its list will be overwritten.
2735 * Please take care of keeping this list alphabetically sorted.
2736 */
2737static struct acl_kw_list acl_kws = {{ },{
Emeric Brun2525b6b2012-10-18 15:59:43 +02002738 { "ssl_c_ca_err", acl_parse_int, smp_fetch_ssl_c_ca_err, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2739 { "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 },
2740 { "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 +02002741 { "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 +02002742 { "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 +02002743 { "ssl_c_notafter", acl_parse_str, smp_fetch_ssl_c_notafter, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2744 { "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 +02002745 { "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 +02002746 { "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 +02002747 { "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 +02002748 { "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 +02002749 { "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 +02002750 { "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 +02002751 { "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 +02002752 { "ssl_f_notafter", acl_parse_str, smp_fetch_ssl_f_notafter, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2753 { "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 +02002754 { "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 +02002755 { "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 +02002756 { "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 +02002757 { "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 +02002758 { "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 +02002759 { "ssl_fc_alg_keysize", acl_parse_str, smp_fetch_ssl_fc_alg_keysize, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2760 { "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 +02002761 { "ssl_fc_has_crt", acl_parse_int, smp_fetch_ssl_fc_has_crt, acl_match_nothing, ACL_USE_L6REQ_PERMANENT, 0 },
2762 { "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 +02002763#ifdef OPENSSL_NPN_NEGOTIATED
Emeric Brun2525b6b2012-10-18 15:59:43 +02002764 { "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 +02002765#endif
Emeric Brun589fcad2012-10-16 14:13:26 +02002766 { "ssl_fc_protocol", acl_parse_str, smp_fetch_ssl_fc_protocol, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2767 { "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 +02002768 { "ssl_fc_sni", acl_parse_str, smp_fetch_ssl_fc_sni, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2769 { "ssl_fc_sni_end", acl_parse_str, smp_fetch_ssl_fc_sni, acl_match_end, ACL_USE_L6REQ_PERMANENT, 0 },
2770 { "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 +02002771 { NULL, NULL, NULL, NULL },
2772}};
2773
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002774/* Note: must not be declared <const> as its list will be overwritten.
2775 * Please take care of keeping this list alphabetically sorted, doing so helps
2776 * all code contributors.
2777 * Optional keywords are also declared with a NULL ->parse() function so that
2778 * the config parser can report an appropriate error when a known keyword was
2779 * not enabled.
2780 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02002781static struct bind_kw_list bind_kws = { "SSL", { }, {
Emeric Brunfb510ea2012-10-05 12:00:26 +02002782 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002783 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
2784 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02002785 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002786 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
2787 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
2788 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002789 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
2790 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
2791 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
2792 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02002793 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
2794 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
2795 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
2796 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002797 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002798 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
2799 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002800 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002801 { NULL, NULL, 0 },
2802}};
Emeric Brun46591952012-05-18 15:47:34 +02002803
Willy Tarreau92faadf2012-10-10 23:04:25 +02002804/* Note: must not be declared <const> as its list will be overwritten.
2805 * Please take care of keeping this list alphabetically sorted, doing so helps
2806 * all code contributors.
2807 * Optional keywords are also declared with a NULL ->parse() function so that
2808 * the config parser can report an appropriate error when a known keyword was
2809 * not enabled.
2810 */
2811static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02002812 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002813 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
2814 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02002815 { "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 +02002816 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002817 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
2818 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
2819 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
2820 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
2821 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
2822 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
2823 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
2824 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02002825 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002826 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02002827 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Willy Tarreau92faadf2012-10-10 23:04:25 +02002828 { NULL, NULL, 0, 0 },
2829}};
2830
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002831/* transport-layer operations for SSL sockets */
2832struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02002833 .snd_buf = ssl_sock_from_buf,
2834 .rcv_buf = ssl_sock_to_buf,
2835 .rcv_pipe = NULL,
2836 .snd_pipe = NULL,
2837 .shutr = NULL,
2838 .shutw = ssl_sock_shutw,
2839 .close = ssl_sock_close,
2840 .init = ssl_sock_init,
2841};
2842
2843__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02002844static void __ssl_sock_init(void)
2845{
Emeric Brun46591952012-05-18 15:47:34 +02002846 STACK_OF(SSL_COMP)* cm;
2847
2848 SSL_library_init();
2849 cm = SSL_COMP_get_compression_methods();
2850 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02002851 sample_register_fetches(&sample_fetch_keywords);
2852 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002853 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02002854 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02002855}
2856
2857/*
2858 * Local variables:
2859 * c-indent-level: 8
2860 * c-basic-offset: 8
2861 * End:
2862 */