blob: 94d66189565298abb1f1cc5400ed77e68e3b767b [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) */
Willy Tarreau20879a02012-12-03 16:32:10 +010096 if (conn->flags & CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +020097 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +010098 conn->err_code = CO_ER_SSL_RENEG;
99 }
Emeric Brune1f38db2012-09-03 20:36:47 +0200100 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200101}
102
Emeric Brune64aef12012-09-21 13:15:06 +0200103/* Callback is called for each certificate of the chain during a verify
104 ok is set to 1 if preverify detect no error on current certificate.
105 Returns 0 to break the handshake, 1 otherwise. */
106int ssl_sock_verifycbk(int ok, X509_STORE_CTX *x_store)
107{
108 SSL *ssl;
109 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +0200110 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +0200111
112 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
113 conn = (struct connection *)SSL_get_app_data(ssl);
114
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200115 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +0200116
Emeric Brun81c00f02012-09-21 14:31:21 +0200117 if (ok) /* no errors */
118 return ok;
119
120 depth = X509_STORE_CTX_get_error_depth(x_store);
121 err = X509_STORE_CTX_get_error(x_store);
122
123 /* check if CA error needs to be ignored */
124 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200125 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
126 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
127 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +0200128 }
129
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100130 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
131 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +0200132 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100133 }
Emeric Brun81c00f02012-09-21 14:31:21 +0200134
Willy Tarreau20879a02012-12-03 16:32:10 +0100135 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +0200136 return 0;
137 }
138
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200139 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
140 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +0200141
Emeric Brun81c00f02012-09-21 14:31:21 +0200142 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100143 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
144 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +0200145 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100146 }
Emeric Brun81c00f02012-09-21 14:31:21 +0200147
Willy Tarreau20879a02012-12-03 16:32:10 +0100148 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +0200149 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +0200150}
151
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200152#ifdef OPENSSL_NPN_NEGOTIATED
153/* This callback is used so that the server advertises the list of
154 * negociable protocols for NPN.
155 */
156static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
157 unsigned int *len, void *arg)
158{
159 struct bind_conf *conf = arg;
160
161 *data = (const unsigned char *)conf->npn_str;
162 *len = conf->npn_len;
163 return SSL_TLSEXT_ERR_OK;
164}
165#endif
166
Emeric Brunfc0421f2012-09-07 17:30:07 +0200167#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
168/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
169 * warning when no match is found, which implies the default (first) cert
170 * will keep being used.
171 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200172static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, struct bind_conf *s)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200173{
174 const char *servername;
175 const char *wildp = NULL;
176 struct ebmb_node *node;
177 int i;
178 (void)al; /* shut gcc stupid warning */
179
180 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
181 if (!servername)
182 return SSL_TLSEXT_ERR_NOACK;
183
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100184 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200185 if (!servername[i])
186 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100187 trash.str[i] = tolower(servername[i]);
188 if (!wildp && (trash.str[i] == '.'))
189 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200190 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100191 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200192
193 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100194 node = ebst_lookup(&s->sni_ctx, trash.str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200195 if (!node) {
196 if (!wildp)
197 return SSL_TLSEXT_ERR_ALERT_WARNING;
198
199 /* lookup in full wildcards names */
200 node = ebst_lookup(&s->sni_w_ctx, wildp);
201 if (!node)
202 return SSL_TLSEXT_ERR_ALERT_WARNING;
203 }
204
205 /* switch ctx */
206 SSL_set_SSL_CTX(ssl, container_of(node, struct sni_ctx, name)->ctx);
207 return SSL_TLSEXT_ERR_OK;
208}
209#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
210
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200211#ifndef OPENSSL_NO_DH
212/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
213 if an error occured, and 0 if parameter not found. */
214int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
215{
216 int ret = -1;
217 BIO *in;
218 DH *dh = NULL;
219
220 in = BIO_new(BIO_s_file());
221 if (in == NULL)
222 goto end;
223
224 if (BIO_read_filename(in, file) <= 0)
225 goto end;
226
227 dh = PEM_read_bio_DHparams(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
228 if (dh) {
229 SSL_CTX_set_tmp_dh(ctx, dh);
230 ret = 1;
231 goto end;
232 }
233
234 ret = 0; /* DH params not found */
235end:
236 if (dh)
237 DH_free(dh);
238
239 if (in)
240 BIO_free(in);
241
242 return ret;
243}
244#endif
245
Emeric Brunfc0421f2012-09-07 17:30:07 +0200246/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
247 * an early error happens and the caller must call SSL_CTX_free() by itelf.
248 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200249int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200250{
251 BIO *in;
252 X509 *x = NULL, *ca;
253 int i, len, err;
254 int ret = -1;
255 int order = 0;
256 X509_NAME *xname;
257 char *str;
258 struct sni_ctx *sc;
259#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
260 STACK_OF(GENERAL_NAME) *names;
261#endif
262
263 in = BIO_new(BIO_s_file());
264 if (in == NULL)
265 goto end;
266
267 if (BIO_read_filename(in, file) <= 0)
268 goto end;
269
270 x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
271 if (x == NULL)
272 goto end;
273
274#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
275 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
276 if (names) {
277 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
278 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
279 if (name->type == GEN_DNS) {
280 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
281 if ((len = strlen(str))) {
282 int j;
283
284 if (*str != '*') {
285 sc = malloc(sizeof(struct sni_ctx) + len + 1);
286 for (j = 0; j < len; j++)
287 sc->name.key[j] = tolower(str[j]);
288 sc->name.key[len] = 0;
289 sc->order = order++;
290 sc->ctx = ctx;
291 ebst_insert(&s->sni_ctx, &sc->name);
292 }
293 else {
294 sc = malloc(sizeof(struct sni_ctx) + len);
295 for (j = 1; j < len; j++)
296 sc->name.key[j-1] = tolower(str[j]);
297 sc->name.key[len-1] = 0;
298 sc->order = order++;
299 sc->ctx = ctx;
300 ebst_insert(&s->sni_w_ctx, &sc->name);
301 }
302 }
303 OPENSSL_free(str);
304 }
305 }
306 }
307 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
308 }
309#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
310
311 xname = X509_get_subject_name(x);
312 i = -1;
313 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
314 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
315 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
316 if ((len = strlen(str))) {
317 int j;
318
319 if (*str != '*') {
320 sc = malloc(sizeof(struct sni_ctx) + len + 1);
321 for (j = 0; j < len; j++)
322 sc->name.key[j] = tolower(str[j]);
323 sc->name.key[len] = 0;
324 sc->order = order++;
325 sc->ctx = ctx;
326 ebst_insert(&s->sni_ctx, &sc->name);
327 }
328 else {
329 sc = malloc(sizeof(struct sni_ctx) + len);
330 for (j = 1; j < len; j++)
331 sc->name.key[j-1] = tolower(str[j]);
332 sc->name.key[len-1] = 0;
333 sc->order = order++;
334 sc->ctx = ctx;
335 ebst_insert(&s->sni_w_ctx, &sc->name);
336 }
337 }
338 OPENSSL_free(str);
339 }
340 }
341
342 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
343 if (!SSL_CTX_use_certificate(ctx, x))
344 goto end;
345
346 if (ctx->extra_certs != NULL) {
347 sk_X509_pop_free(ctx->extra_certs, X509_free);
348 ctx->extra_certs = NULL;
349 }
350
351 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata))) {
352 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
353 X509_free(ca);
354 goto end;
355 }
356 }
357
358 err = ERR_get_error();
359 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
360 /* we successfully reached the last cert in the file */
361 ret = 1;
362 }
363 ERR_clear_error();
364
365end:
366 if (x)
367 X509_free(x);
368
369 if (in)
370 BIO_free(in);
371
372 return ret;
373}
374
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200375static 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 +0200376{
377 int ret;
378 SSL_CTX *ctx;
379
380 ctx = SSL_CTX_new(SSLv23_server_method());
381 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200382 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
383 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200384 return 1;
385 }
386
387 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200388 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
389 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200390 SSL_CTX_free(ctx);
391 return 1;
392 }
393
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200394 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200395 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200396 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
397 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200398 if (ret < 0) /* serious error, must do that ourselves */
399 SSL_CTX_free(ctx);
400 return 1;
401 }
Emeric Brun61694ab2012-10-26 13:35:33 +0200402
403 if (SSL_CTX_check_private_key(ctx) <= 0) {
404 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
405 err && *err ? *err : "", path);
406 return 1;
407 }
408
Emeric Brunfc0421f2012-09-07 17:30:07 +0200409 /* we must not free the SSL_CTX anymore below, since it's already in
410 * the tree, so it will be discovered and cleaned in time.
411 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200412#ifndef OPENSSL_NO_DH
413 ret = ssl_sock_load_dh_params(ctx, path);
414 if (ret < 0) {
415 if (err)
416 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
417 *err ? *err : "", path);
418 return 1;
419 }
420#endif
421
Emeric Brunfc0421f2012-09-07 17:30:07 +0200422#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200423 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200424 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
425 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +0200426 return 1;
427 }
428#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200429 if (!bind_conf->default_ctx)
430 bind_conf->default_ctx = ctx;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200431
432 return 0;
433}
434
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200435int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200436{
437 struct dirent *de;
438 DIR *dir;
439 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +0100440 char *end;
441 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200442 int cfgerr = 0;
443
444 if (!(dir = opendir(path)))
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200445 return ssl_sock_load_cert_file(path, bind_conf, curproxy, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200446
447 /* strip trailing slashes, including first one */
448 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
449 *end = 0;
450
Emeric Brunfc0421f2012-09-07 17:30:07 +0200451 while ((de = readdir(dir))) {
Willy Tarreauee2663b2012-12-06 11:36:59 +0100452 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200453 if (stat(fp, &buf) != 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200454 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
455 err && *err ? *err : "", fp, strerror(errno));
Emeric Brunfc0421f2012-09-07 17:30:07 +0200456 cfgerr++;
457 continue;
458 }
459 if (!S_ISREG(buf.st_mode))
460 continue;
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200461 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, curproxy, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200462 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200463 closedir(dir);
464 return cfgerr;
465}
466
467#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
468#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
469#endif
470
471#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
472#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
Willy Tarreau7d588ee2012-11-26 18:47:31 +0100473#define SSL_renegotiate_pending(arg) 0
Emeric Brunfc0421f2012-09-07 17:30:07 +0200474#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200475#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
476#define SSL_OP_SINGLE_ECDH_USE 0
477#endif
Emeric Brun2d0c4822012-10-02 13:45:20 +0200478#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
479#define SSL_OP_NO_TICKET 0
480#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200481#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
482#define SSL_OP_NO_COMPRESSION 0
483#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +0200484#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
485#define SSL_OP_NO_TLSv1_1 0
486#endif
487#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
488#define SSL_OP_NO_TLSv1_2 0
489#endif
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200490#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
491#define SSL_OP_SINGLE_DH_USE 0
492#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200493#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
494#define SSL_OP_SINGLE_ECDH_USE 0
495#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200496#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
497#define SSL_MODE_RELEASE_BUFFERS 0
498#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200499int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy *curproxy)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200500{
501 int cfgerr = 0;
502 int ssloptions =
503 SSL_OP_ALL | /* all known workarounds for bugs */
504 SSL_OP_NO_SSLv2 |
505 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200506 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +0200507 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +0200508 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
509 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200510 int sslmode =
511 SSL_MODE_ENABLE_PARTIAL_WRITE |
512 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
513 SSL_MODE_RELEASE_BUFFERS;
514
Emeric Brun89675492012-10-05 13:48:26 +0200515 if (bind_conf->ssl_options & BC_SSL_O_NO_SSLV3)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200516 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brun89675492012-10-05 13:48:26 +0200517 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV10)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200518 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun89675492012-10-05 13:48:26 +0200519 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV11)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200520 ssloptions |= SSL_OP_NO_TLSv1_1;
Emeric Brun89675492012-10-05 13:48:26 +0200521 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV12)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200522 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun89675492012-10-05 13:48:26 +0200523 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
Emeric Brun2d0c4822012-10-02 13:45:20 +0200524 ssloptions |= SSL_OP_NO_TICKET;
Emeric Brun2cb7ae52012-10-05 14:14:21 +0200525 if (bind_conf->ssl_options & BC_SSL_O_USE_SSLV3)
526 SSL_CTX_set_ssl_version(ctx, SSLv3_server_method());
527 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV10)
528 SSL_CTX_set_ssl_version(ctx, TLSv1_server_method());
529#if SSL_OP_NO_TLSv1_1
530 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV11)
531 SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method());
532#endif
533#if SSL_OP_NO_TLSv1_2
534 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV12)
535 SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method());
536#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200537
538 SSL_CTX_set_options(ctx, ssloptions);
539 SSL_CTX_set_mode(ctx, sslmode);
Emeric Brune64aef12012-09-21 13:15:06 +0200540 SSL_CTX_set_verify(ctx, bind_conf->verify ? bind_conf->verify : SSL_VERIFY_NONE, ssl_sock_verifycbk);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200541 if (bind_conf->verify & SSL_VERIFY_PEER) {
Emeric Brunfb510ea2012-10-05 12:00:26 +0200542 if (bind_conf->ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200543 /* load CAfile to verify */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200544 if (!SSL_CTX_load_verify_locations(ctx, bind_conf->ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200545 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200546 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200547 cfgerr++;
548 }
549 /* set CA names fo client cert request, function returns void */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200550 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(bind_conf->ca_file));
Emeric Brund94b3fe2012-09-20 18:23:56 +0200551 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200552#ifdef X509_V_FLAG_CRL_CHECK
Emeric Brunfb510ea2012-10-05 12:00:26 +0200553 if (bind_conf->crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200554 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
555
Emeric Brunfb510ea2012-10-05 12:00:26 +0200556 if (!store || !X509_STORE_load_locations(store, bind_conf->crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200557 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200558 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200559 cfgerr++;
560 }
Emeric Brun561e5742012-10-02 15:20:55 +0200561 else {
562 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
563 }
Emeric Brund94b3fe2012-09-20 18:23:56 +0200564 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200565#endif
Emeric Brund94b3fe2012-09-20 18:23:56 +0200566 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200567
Emeric Brun4f65bff2012-11-16 15:11:00 +0100568 if (global.tune.ssllifetime)
569 SSL_CTX_set_timeout(ctx, global.tune.ssllifetime);
570
Emeric Brunfc0421f2012-09-07 17:30:07 +0200571 shared_context_set_cache(ctx);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200572 if (bind_conf->ciphers &&
573 !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200574 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 +0200575 curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200576 cfgerr++;
577 }
578
579 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200580#ifdef OPENSSL_NPN_NEGOTIATED
581 if (bind_conf->npn_str)
582 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
583#endif
584
Emeric Brunfc0421f2012-09-07 17:30:07 +0200585#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
586 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200587 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200588#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200589#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
590 if (bind_conf->ecdhe) {
591 int i;
592 EC_KEY *ecdh;
593
594 i = OBJ_sn2nid(bind_conf->ecdhe);
595 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
596 Alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
597 curproxy->id, bind_conf->ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
598 cfgerr++;
599 }
600 else {
601 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
602 EC_KEY_free(ecdh);
603 }
604 }
605#endif
606
Emeric Brunfc0421f2012-09-07 17:30:07 +0200607 return cfgerr;
608}
609
Emeric Brun94324a42012-10-11 14:00:19 +0200610/* prepare ssl context from servers options. Returns an error count */
611int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
612{
613 int cfgerr = 0;
614 int options =
615 SSL_OP_ALL | /* all known workarounds for bugs */
616 SSL_OP_NO_SSLv2 |
617 SSL_OP_NO_COMPRESSION;
618 int mode =
619 SSL_MODE_ENABLE_PARTIAL_WRITE |
620 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
621 SSL_MODE_RELEASE_BUFFERS;
622
623 /* Initiate SSL context for current server */
624 srv->ssl_ctx.reused_sess = NULL;
625 if (srv->use_ssl)
626 srv->xprt = &ssl_sock;
627 if (srv->check.use_ssl)
628 srv->check.xprt = &ssl_sock;
629
630 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
631 if (!srv->ssl_ctx.ctx) {
632 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
633 proxy_type_str(curproxy), curproxy->id,
634 srv->id);
635 cfgerr++;
636 return cfgerr;
637 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200638 if (srv->ssl_ctx.client_crt) {
639 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
640 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
641 proxy_type_str(curproxy), curproxy->id,
642 srv->id, srv->ssl_ctx.client_crt);
643 cfgerr++;
644 }
645 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
646 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
647 proxy_type_str(curproxy), curproxy->id,
648 srv->id, srv->ssl_ctx.client_crt);
649 cfgerr++;
650 }
651 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
652 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
653 proxy_type_str(curproxy), curproxy->id,
654 srv->id, srv->ssl_ctx.client_crt);
655 cfgerr++;
656 }
657 }
Emeric Brun94324a42012-10-11 14:00:19 +0200658
659 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
660 options |= SSL_OP_NO_SSLv3;
661 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
662 options |= SSL_OP_NO_TLSv1;
663 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
664 options |= SSL_OP_NO_TLSv1_1;
665 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
666 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200667 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
668 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200669 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
670 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
671 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
672 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
673#if SSL_OP_NO_TLSv1_1
674 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
675 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
676#endif
677#if SSL_OP_NO_TLSv1_2
678 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
679 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
680#endif
681
682 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
683 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Emeric Brunef42d922012-10-11 16:11:36 +0200684 SSL_CTX_set_verify(srv->ssl_ctx.ctx, srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE, NULL);
685 if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
686 if (srv->ssl_ctx.ca_file) {
687 /* load CAfile to verify */
688 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
689 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
690 curproxy->id, srv->id,
691 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
692 cfgerr++;
693 }
694 }
695#ifdef X509_V_FLAG_CRL_CHECK
696 if (srv->ssl_ctx.crl_file) {
697 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
698
699 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
700 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
701 curproxy->id, srv->id,
702 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
703 cfgerr++;
704 }
705 else {
706 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
707 }
708 }
709#endif
710 }
711
Emeric Brun4f65bff2012-11-16 15:11:00 +0100712 if (global.tune.ssllifetime)
713 SSL_CTX_set_timeout(srv->ssl_ctx.ctx, global.tune.ssllifetime);
714
Emeric Brun94324a42012-10-11 14:00:19 +0200715 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
716 if (srv->ssl_ctx.ciphers &&
717 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
718 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
719 curproxy->id, srv->id,
720 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
721 cfgerr++;
722 }
723
724 return cfgerr;
725}
726
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200727/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200728 * be NULL, in which case nothing is done. Returns the number of errors
729 * encountered.
730 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200731int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200732{
733 struct ebmb_node *node;
734 struct sni_ctx *sni;
735 int err = 0;
736
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200737 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200738 return 0;
739
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200740 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200741 while (node) {
742 sni = ebmb_entry(node, struct sni_ctx, name);
743 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200744 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200745 node = ebmb_next(node);
746 }
747
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200748 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200749 while (node) {
750 sni = ebmb_entry(node, struct sni_ctx, name);
751 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200752 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200753 node = ebmb_next(node);
754 }
755 return err;
756}
757
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200758/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200759 * be NULL, in which case nothing is done. The default_ctx is nullified too.
760 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200761void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200762{
763 struct ebmb_node *node, *back;
764 struct sni_ctx *sni;
765
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200766 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200767 return;
768
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200769 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200770 while (node) {
771 sni = ebmb_entry(node, struct sni_ctx, name);
772 back = ebmb_next(node);
773 ebmb_delete(node);
774 if (!sni->order) /* only free the CTX on its first occurrence */
775 SSL_CTX_free(sni->ctx);
776 free(sni);
777 node = back;
778 }
779
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200780 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200781 while (node) {
782 sni = ebmb_entry(node, struct sni_ctx, name);
783 back = ebmb_next(node);
784 ebmb_delete(node);
785 if (!sni->order) /* only free the CTX on its first occurrence */
786 SSL_CTX_free(sni->ctx);
787 free(sni);
788 node = back;
789 }
790
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200791 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +0200792}
793
Emeric Brun46591952012-05-18 15:47:34 +0200794/*
795 * This function is called if SSL * context is not yet allocated. The function
796 * is designed to be called before any other data-layer operation and sets the
797 * handshake flag on the connection. It is safe to call it multiple times.
798 * It returns 0 on success and -1 in error case.
799 */
800static int ssl_sock_init(struct connection *conn)
801{
802 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200803 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200804 return 0;
805
Willy Tarreau20879a02012-12-03 16:32:10 +0100806 if (global.maxsslconn && sslconns >= global.maxsslconn) {
807 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +0200808 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100809 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200810
Emeric Brun46591952012-05-18 15:47:34 +0200811 /* If it is in client mode initiate SSL session
812 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100813 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200814 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100815 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +0100816 if (!conn->xprt_ctx) {
817 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +0200818 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100819 }
Emeric Brun46591952012-05-18 15:47:34 +0200820
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200821 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100822 if (objt_server(conn->target)->ssl_ctx.reused_sess)
823 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +0200824
825 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200826 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200827
828 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200829 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200830
831 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200832 return 0;
833 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100834 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200835 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100836 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +0100837 if (!conn->xprt_ctx) {
838 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +0200839 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100840 }
Emeric Brun46591952012-05-18 15:47:34 +0200841
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200842 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200843
844 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200845 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200846
Emeric Brune1f38db2012-09-03 20:36:47 +0200847 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200848 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +0200849
Emeric Brun46591952012-05-18 15:47:34 +0200850 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200851 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200852
853 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200854 return 0;
855 }
856 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +0100857 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +0200858 return -1;
859}
860
861
862/* This is the callback which is used when an SSL handshake is pending. It
863 * updates the FD status if it wants some polling before being called again.
864 * It returns 0 if it fails in a fatal way or needs to poll to go further,
865 * otherwise it returns non-zero and removes itself from the connection's
866 * flags (the bit is provided in <flag> by the caller).
867 */
868int ssl_sock_handshake(struct connection *conn, unsigned int flag)
869{
870 int ret;
871
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200872 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200873 goto out_error;
874
Emeric Brun674b7432012-11-08 19:21:55 +0100875 /* If we use SSL_do_handshake to process a reneg initiated by
876 * the remote peer, it sometimes returns SSL_ERROR_SSL.
877 * Usually SSL_write and SSL_read are used and process implicitly
878 * the reneg handshake.
879 * Here we use SSL_peek as a workaround for reneg.
880 */
881 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
882 char c;
883
884 ret = SSL_peek(conn->xprt_ctx, &c, 1);
885 if (ret <= 0) {
886 /* handshake may have not been completed, let's find why */
887 ret = SSL_get_error(conn->xprt_ctx, ret);
888 if (ret == SSL_ERROR_WANT_WRITE) {
889 /* SSL handshake needs to write, L4 connection may not be ready */
890 __conn_sock_stop_recv(conn);
891 __conn_sock_poll_send(conn);
892 return 0;
893 }
894 else if (ret == SSL_ERROR_WANT_READ) {
895 /* handshake may have been completed but we have
896 * no more data to read.
897 */
898 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
899 ret = 1;
900 goto reneg_ok;
901 }
902 /* SSL handshake needs to read, L4 connection is ready */
903 if (conn->flags & CO_FL_WAIT_L4_CONN)
904 conn->flags &= ~CO_FL_WAIT_L4_CONN;
905 __conn_sock_stop_send(conn);
906 __conn_sock_poll_recv(conn);
907 return 0;
908 }
909 else if (ret == SSL_ERROR_SYSCALL) {
910 /* if errno is null, then connection was successfully established */
911 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
912 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +0100913 if (!conn->err_code) {
914 if (!((SSL *)conn->xprt_ctx)->packet_length)
915 if (!errno)
916 conn->err_code = CO_ER_SSL_EMPTY;
917 else
918 conn->err_code = CO_ER_SSL_ABORT;
919 else
920 conn->err_code = CO_ER_SSL_HANDSHAKE;
921 }
Emeric Brun674b7432012-11-08 19:21:55 +0100922 goto out_error;
923 }
924 else {
925 /* Fail on all other handshake errors */
926 /* Note: OpenSSL may leave unread bytes in the socket's
927 * buffer, causing an RST to be emitted upon close() on
928 * TCP sockets. We first try to drain possibly pending
929 * data to avoid this as much as possible.
930 */
931 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Willy Tarreau20879a02012-12-03 16:32:10 +0100932 if (!conn->err_code)
933 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +0100934 goto out_error;
935 }
936 }
937 /* read some data: consider handshake completed */
938 goto reneg_ok;
939 }
940
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200941 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200942 if (ret != 1) {
943 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200944 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +0200945
946 if (ret == SSL_ERROR_WANT_WRITE) {
947 /* SSL handshake needs to write, L4 connection may not be ready */
948 __conn_sock_stop_recv(conn);
949 __conn_sock_poll_send(conn);
950 return 0;
951 }
952 else if (ret == SSL_ERROR_WANT_READ) {
953 /* SSL handshake needs to read, L4 connection is ready */
954 if (conn->flags & CO_FL_WAIT_L4_CONN)
955 conn->flags &= ~CO_FL_WAIT_L4_CONN;
956 __conn_sock_stop_send(conn);
957 __conn_sock_poll_recv(conn);
958 return 0;
959 }
Willy Tarreau89230192012-09-28 20:22:13 +0200960 else if (ret == SSL_ERROR_SYSCALL) {
961 /* if errno is null, then connection was successfully established */
962 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
963 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +0100964
965 if (!((SSL *)conn->xprt_ctx)->packet_length)
966 if (!errno)
967 conn->err_code = CO_ER_SSL_EMPTY;
968 else
969 conn->err_code = CO_ER_SSL_ABORT;
970 else
971 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +0200972 goto out_error;
973 }
Emeric Brun46591952012-05-18 15:47:34 +0200974 else {
975 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +0200976 /* Note: OpenSSL may leave unread bytes in the socket's
977 * buffer, causing an RST to be emitted upon close() on
978 * TCP sockets. We first try to drain possibly pending
979 * data to avoid this as much as possible.
980 */
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100981 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Willy Tarreau20879a02012-12-03 16:32:10 +0100982 if (!conn->err_code)
983 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +0200984 goto out_error;
985 }
986 }
987
Emeric Brun674b7432012-11-08 19:21:55 +0100988reneg_ok:
989
Emeric Brun46591952012-05-18 15:47:34 +0200990 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100991 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200992 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +0200993 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100994 if (objt_server(conn->target)->ssl_ctx.reused_sess)
995 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +0200996
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100997 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200998 }
999 }
1000
1001 /* The connection is now established at both layers, it's time to leave */
1002 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1003 return 1;
1004
1005 out_error:
Emeric Brun9fa89732012-10-04 17:09:56 +02001006 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001007 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1008 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1009 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001010 }
1011
Emeric Brun46591952012-05-18 15:47:34 +02001012 /* Fail on all other handshake errors */
1013 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001014 if (!conn->err_code)
1015 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001016 return 0;
1017}
1018
1019/* Receive up to <count> bytes from connection <conn>'s socket and store them
1020 * into buffer <buf>. The caller must ensure that <count> is always smaller
1021 * than the buffer's size. Only one call to recv() is performed, unless the
1022 * buffer wraps, in which case a second call may be performed. The connection's
1023 * flags are updated with whatever special event is detected (error, read0,
1024 * empty). The caller is responsible for taking care of those events and
1025 * avoiding the call if inappropriate. The function does not call the
1026 * connection's polling update function, so the caller is responsible for this.
1027 */
1028static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1029{
1030 int ret, done = 0;
1031 int try = count;
1032
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001033 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001034 goto out_error;
1035
1036 if (conn->flags & CO_FL_HANDSHAKE)
1037 /* a handshake was requested */
1038 return 0;
1039
1040 /* compute the maximum block size we can read at once. */
1041 if (buffer_empty(buf)) {
1042 /* let's realign the buffer to optimize I/O */
1043 buf->p = buf->data;
1044 }
1045 else if (buf->data + buf->o < buf->p &&
1046 buf->p + buf->i < buf->data + buf->size) {
1047 /* remaining space wraps at the end, with a moving limit */
1048 if (try > buf->data + buf->size - (buf->p + buf->i))
1049 try = buf->data + buf->size - (buf->p + buf->i);
1050 }
1051
1052 /* read the largest possible block. For this, we perform only one call
1053 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1054 * in which case we accept to do it once again. A new attempt is made on
1055 * EINTR too.
1056 */
1057 while (try) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001058 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001059 if (conn->flags & CO_FL_ERROR) {
1060 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
1061 break;
1062 }
Emeric Brun46591952012-05-18 15:47:34 +02001063 if (ret > 0) {
1064 buf->i += ret;
1065 done += ret;
1066 if (ret < try)
1067 break;
1068 count -= ret;
1069 try = count;
1070 }
1071 else if (ret == 0) {
1072 goto read0;
1073 }
1074 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001075 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001076 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001077 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001078 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001079 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001080 break;
1081 }
1082 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001083 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1084 /* handshake is running, and it may need to re-enable read */
1085 conn->flags |= CO_FL_SSL_WAIT_HS;
1086 __conn_sock_want_recv(conn);
1087 break;
1088 }
Emeric Brun46591952012-05-18 15:47:34 +02001089 /* we need to poll for retry a read later */
1090 __conn_data_poll_recv(conn);
1091 break;
1092 }
1093 /* otherwise it's a real error */
1094 goto out_error;
1095 }
1096 }
1097 return done;
1098
1099 read0:
1100 conn_sock_read0(conn);
1101 return done;
1102 out_error:
1103 conn->flags |= CO_FL_ERROR;
1104 return done;
1105}
1106
1107
1108/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1109 * <flags> may contain MSG_MORE to make the system hold on without sending
1110 * data too fast, but this flag is ignored at the moment.
1111 * Only one call to send() is performed, unless the buffer wraps, in which case
1112 * a second call may be performed. The connection's flags are updated with
1113 * whatever special event is detected (error, empty). The caller is responsible
1114 * for taking care of those events and avoiding the call if inappropriate. The
1115 * function does not call the connection's polling update function, so the caller
1116 * is responsible for this.
1117 */
1118static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1119{
1120 int ret, try, done;
1121
1122 done = 0;
1123
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001124 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001125 goto out_error;
1126
1127 if (conn->flags & CO_FL_HANDSHAKE)
1128 /* a handshake was requested */
1129 return 0;
1130
1131 /* send the largest possible block. For this we perform only one call
1132 * to send() unless the buffer wraps and we exactly fill the first hunk,
1133 * in which case we accept to do it once again.
1134 */
1135 while (buf->o) {
1136 try = buf->o;
1137 /* outgoing data may wrap at the end */
1138 if (buf->data + try > buf->p)
1139 try = buf->data + try - buf->p;
1140
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001141 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001142 if (conn->flags & CO_FL_ERROR) {
1143 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
1144 break;
1145 }
Emeric Brun46591952012-05-18 15:47:34 +02001146 if (ret > 0) {
1147 buf->o -= ret;
1148 done += ret;
1149
1150 if (likely(!buffer_len(buf)))
1151 /* optimize data alignment in the buffer */
1152 buf->p = buf->data;
1153
1154 /* if the system buffer is full, don't insist */
1155 if (ret < try)
1156 break;
1157 }
1158 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001159 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001160 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001161 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1162 /* handshake is running, and it may need to re-enable write */
1163 conn->flags |= CO_FL_SSL_WAIT_HS;
1164 __conn_sock_want_send(conn);
1165 break;
1166 }
Emeric Brun46591952012-05-18 15:47:34 +02001167 /* we need to poll to retry a write later */
1168 __conn_data_poll_send(conn);
1169 break;
1170 }
1171 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001172 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001173 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001174 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001175 break;
1176 }
1177 goto out_error;
1178 }
1179 }
1180 return done;
1181
1182 out_error:
1183 conn->flags |= CO_FL_ERROR;
1184 return done;
1185}
1186
1187
1188static void ssl_sock_close(struct connection *conn) {
1189
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001190 if (conn->xprt_ctx) {
1191 SSL_free(conn->xprt_ctx);
1192 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001193 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001194 }
Emeric Brun46591952012-05-18 15:47:34 +02001195}
1196
1197/* This function tries to perform a clean shutdown on an SSL connection, and in
1198 * any case, flags the connection as reusable if no handshake was in progress.
1199 */
1200static void ssl_sock_shutw(struct connection *conn, int clean)
1201{
1202 if (conn->flags & CO_FL_HANDSHAKE)
1203 return;
1204 /* no handshake was in progress, try a clean ssl shutdown */
1205 if (clean)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001206 SSL_shutdown(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001207
1208 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001209 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001210}
1211
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001212/* used for logging, may be changed for a sample fetch later */
1213const char *ssl_sock_get_cipher_name(struct connection *conn)
1214{
1215 if (!conn->xprt && !conn->xprt_ctx)
1216 return NULL;
1217 return SSL_get_cipher_name(conn->xprt_ctx);
1218}
1219
1220/* used for logging, may be changed for a sample fetch later */
1221const char *ssl_sock_get_proto_version(struct connection *conn)
1222{
1223 if (!conn->xprt && !conn->xprt_ctx)
1224 return NULL;
1225 return SSL_get_version(conn->xprt_ctx);
1226}
1227
Willy Tarreau8d598402012-10-22 17:58:39 +02001228/* Extract a serial from a cert, and copy it to a chunk.
1229 * Returns 1 if serial is found and copied, 0 if no serial found and
1230 * -1 if output is not large enough.
1231 */
1232static int
1233ssl_sock_get_serial(X509 *crt, struct chunk *out)
1234{
1235 ASN1_INTEGER *serial;
1236
1237 serial = X509_get_serialNumber(crt);
1238 if (!serial)
1239 return 0;
1240
1241 if (out->size < serial->length)
1242 return -1;
1243
1244 memcpy(out->str, serial->data, serial->length);
1245 out->len = serial->length;
1246 return 1;
1247}
1248
Emeric Brunce5ad802012-10-22 14:11:22 +02001249
1250/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1251 * Returns 1 if serial is found and copied, 0 if no valid time found
1252 * and -1 if output is not large enough.
1253 */
1254static int
1255ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1256{
1257 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1258 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1259
1260 if (gentm->length < 12)
1261 return 0;
1262 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1263 return 0;
1264 if (out->size < gentm->length-2)
1265 return -1;
1266
1267 memcpy(out->str, gentm->data+2, gentm->length-2);
1268 out->len = gentm->length-2;
1269 return 1;
1270 }
1271 else if (tm->type == V_ASN1_UTCTIME) {
1272 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1273
1274 if (utctm->length < 10)
1275 return 0;
1276 if (utctm->data[0] >= 0x35)
1277 return 0;
1278 if (out->size < utctm->length)
1279 return -1;
1280
1281 memcpy(out->str, utctm->data, utctm->length);
1282 out->len = utctm->length;
1283 return 1;
1284 }
1285
1286 return 0;
1287}
1288
Emeric Brun87855892012-10-17 17:39:35 +02001289/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1290 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1291 */
1292static int
1293ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1294{
1295 X509_NAME_ENTRY *ne;
1296 int i, j, n;
1297 int cur = 0;
1298 const char *s;
1299 char tmp[128];
1300
1301 out->len = 0;
1302 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1303 if (pos < 0)
1304 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1305 else
1306 j = i;
1307
1308 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1309 n = OBJ_obj2nid(ne->object);
1310 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1311 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1312 s = tmp;
1313 }
1314
1315 if (chunk_strcasecmp(entry, s) != 0)
1316 continue;
1317
1318 if (pos < 0)
1319 cur--;
1320 else
1321 cur++;
1322
1323 if (cur != pos)
1324 continue;
1325
1326 if (ne->value->length > out->size)
1327 return -1;
1328
1329 memcpy(out->str, ne->value->data, ne->value->length);
1330 out->len = ne->value->length;
1331 return 1;
1332 }
1333
1334 return 0;
1335
1336}
1337
1338/* Extract and format full DN from a X509_NAME and copy result into a chunk
1339 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1340 */
1341static int
1342ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1343{
1344 X509_NAME_ENTRY *ne;
1345 int i, n, ln;
1346 int l = 0;
1347 const char *s;
1348 char *p;
1349 char tmp[128];
1350
1351 out->len = 0;
1352 p = out->str;
1353 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1354 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1355 n = OBJ_obj2nid(ne->object);
1356 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1357 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1358 s = tmp;
1359 }
1360 ln = strlen(s);
1361
1362 l += 1 + ln + 1 + ne->value->length;
1363 if (l > out->size)
1364 return -1;
1365 out->len = l;
1366
1367 *(p++)='/';
1368 memcpy(p, s, ln);
1369 p += ln;
1370 *(p++)='=';
1371 memcpy(p, ne->value->data, ne->value->length);
1372 p += ne->value->length;
1373 }
1374
1375 if (!out->len)
1376 return 0;
1377
1378 return 1;
1379}
1380
Willy Tarreau7875d092012-09-10 08:20:03 +02001381/***** Below are some sample fetching functions for ACL/patterns *****/
1382
Emeric Brune64aef12012-09-21 13:15:06 +02001383/* boolean, returns true if client cert was present */
1384static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001385smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1386 const struct arg *args, struct sample *smp)
Emeric Brune64aef12012-09-21 13:15:06 +02001387{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001388 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001389 return 0;
1390
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001391 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001392 smp->flags |= SMP_F_MAY_CHANGE;
1393 return 0;
1394 }
1395
1396 smp->flags = 0;
1397 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001398 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001399
1400 return 1;
1401}
1402
Willy Tarreau8d598402012-10-22 17:58:39 +02001403/* bin, returns serial in a binary chunk */
1404static int
1405smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1406 const struct arg *args, struct sample *smp)
1407{
1408 X509 *crt = NULL;
1409 int ret = 0;
1410 struct chunk *smp_trash;
1411
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001412 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001413 return 0;
1414
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001415 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001416 smp->flags |= SMP_F_MAY_CHANGE;
1417 return 0;
1418 }
1419
1420 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001421 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001422 if (!crt)
1423 goto out;
1424
1425 smp_trash = sample_get_trash_chunk();
1426 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1427 goto out;
1428
1429 smp->data.str = *smp_trash;
1430 smp->type = SMP_T_BIN;
1431 ret = 1;
1432out:
1433 if (crt)
1434 X509_free(crt);
1435 return ret;
1436}
Emeric Brune64aef12012-09-21 13:15:06 +02001437
Emeric Brunce5ad802012-10-22 14:11:22 +02001438/*str, returns notafter date in ASN1_UTCTIME format */
1439static int
1440smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1441 const struct arg *args, struct sample *smp)
1442{
1443 X509 *crt = NULL;
1444 int ret = 0;
1445 struct chunk *smp_trash;
1446
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001447 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001448 return 0;
1449
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001450 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001451 smp->flags |= SMP_F_MAY_CHANGE;
1452 return 0;
1453 }
1454
1455 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001456 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001457 if (!crt)
1458 goto out;
1459
1460 smp_trash = sample_get_trash_chunk();
1461 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1462 goto out;
1463
1464 smp->data.str = *smp_trash;
1465 smp->type = SMP_T_STR;
1466 ret = 1;
1467out:
1468 if (crt)
1469 X509_free(crt);
1470 return ret;
1471}
1472
Emeric Brun87855892012-10-17 17:39:35 +02001473/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1474static int
1475smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1476 const struct arg *args, struct sample *smp)
1477{
1478 X509 *crt = NULL;
1479 X509_NAME *name;
1480 int ret = 0;
1481 struct chunk *smp_trash;
1482
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001483 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001484 return 0;
1485
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001486 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001487 smp->flags |= SMP_F_MAY_CHANGE;
1488 return 0;
1489 }
1490
1491 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001492 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001493 if (!crt)
1494 goto out;
1495
1496 name = X509_get_issuer_name(crt);
1497 if (!name)
1498 goto out;
1499
1500 smp_trash = sample_get_trash_chunk();
1501 if (args && args[0].type == ARGT_STR) {
1502 int pos = 1;
1503
1504 if (args[1].type == ARGT_SINT)
1505 pos = args[1].data.sint;
1506 else if (args[1].type == ARGT_UINT)
1507 pos =(int)args[1].data.uint;
1508
1509 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1510 goto out;
1511 }
1512 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1513 goto out;
1514
1515 smp->type = SMP_T_STR;
1516 smp->data.str = *smp_trash;
1517 ret = 1;
1518out:
1519 if (crt)
1520 X509_free(crt);
1521 return ret;
1522}
1523
Emeric Brunce5ad802012-10-22 14:11:22 +02001524/*str, returns notbefore date in ASN1_UTCTIME format */
1525static int
1526smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1527 const struct arg *args, struct sample *smp)
1528{
1529 X509 *crt = NULL;
1530 int ret = 0;
1531 struct chunk *smp_trash;
1532
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001533 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001534 return 0;
1535
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001536 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001537 smp->flags |= SMP_F_MAY_CHANGE;
1538 return 0;
1539 }
1540
1541 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001542 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001543 if (!crt)
1544 goto out;
1545
1546 smp_trash = sample_get_trash_chunk();
1547 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1548 goto out;
1549
1550 smp->data.str = *smp_trash;
1551 smp->type = SMP_T_STR;
1552 ret = 1;
1553out:
1554 if (crt)
1555 X509_free(crt);
1556 return ret;
1557}
1558
Emeric Brun87855892012-10-17 17:39:35 +02001559/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1560static int
1561smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1562 const struct arg *args, struct sample *smp)
1563{
1564 X509 *crt = NULL;
1565 X509_NAME *name;
1566 int ret = 0;
1567 struct chunk *smp_trash;
1568
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001569 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001570 return 0;
1571
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001572 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001573 smp->flags |= SMP_F_MAY_CHANGE;
1574 return 0;
1575 }
1576
1577 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001578 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001579 if (!crt)
1580 goto out;
1581
1582 name = X509_get_subject_name(crt);
1583 if (!name)
1584 goto out;
1585
1586 smp_trash = sample_get_trash_chunk();
1587 if (args && args[0].type == ARGT_STR) {
1588 int pos = 1;
1589
1590 if (args[1].type == ARGT_SINT)
1591 pos = args[1].data.sint;
1592 else if (args[1].type == ARGT_UINT)
1593 pos =(int)args[1].data.uint;
1594
1595 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1596 goto out;
1597 }
1598 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1599 goto out;
1600
1601 smp->type = SMP_T_STR;
1602 smp->data.str = *smp_trash;
1603 ret = 1;
1604out:
1605 if (crt)
1606 X509_free(crt);
1607 return ret;
1608}
Emeric Bruna7359fd2012-10-17 15:03:11 +02001609/* integer, returns the client certificate version */
1610static int
1611smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1612 const struct arg *args, struct sample *smp)
1613{
1614 X509 *crt;
1615
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001616 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001617 return 0;
1618
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001619 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001620 smp->flags |= SMP_F_MAY_CHANGE;
1621 return 0;
1622 }
1623
1624 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001625 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001626 if (!crt)
1627 return 0;
1628
1629 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1630 X509_free(crt);
1631 smp->type = SMP_T_UINT;
1632
1633 return 1;
1634}
1635
Emeric Brun7f56e742012-10-19 18:15:40 +02001636/* str, returns the client certificate sig alg */
1637static int
1638smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1639 const struct arg *args, struct sample *smp)
1640{
1641 X509 *crt;
1642 int nid;
1643
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001644 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02001645 return 0;
1646
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001647 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02001648 smp->flags |= SMP_F_MAY_CHANGE;
1649 return 0;
1650 }
1651
1652 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001653 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02001654 if (!crt)
1655 return 0;
1656
1657 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1658
1659 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1660 if (!smp->data.str.str)
1661 return 0;
1662
1663 smp->type = SMP_T_CSTR;
1664 smp->data.str.len = strlen(smp->data.str.str);
1665 X509_free(crt);
1666
1667 return 1;
1668}
1669
Emeric Brun521a0112012-10-22 12:22:55 +02001670/* str, returns the client certificate key alg */
1671static int
1672smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1673 const struct arg *args, struct sample *smp)
1674{
1675 X509 *crt;
1676 int nid;
1677
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001678 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02001679 return 0;
1680
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001681 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02001682 smp->flags |= SMP_F_MAY_CHANGE;
1683 return 0;
1684 }
1685
1686 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001687 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02001688 if (!crt)
1689 return 0;
1690
1691 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1692
1693 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1694 if (!smp->data.str.str)
1695 return 0;
1696
1697 smp->type = SMP_T_CSTR;
1698 smp->data.str.len = strlen(smp->data.str.str);
1699 X509_free(crt);
1700
1701 return 1;
1702}
1703
Emeric Brun2525b6b2012-10-18 15:59:43 +02001704/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02001705static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001706smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau7875d092012-09-10 08:20:03 +02001707 const struct arg *args, struct sample *smp)
1708{
1709 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001710 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02001711 return 1;
1712}
1713
Emeric Brun2525b6b2012-10-18 15:59:43 +02001714/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02001715static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001716smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1717 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02001718{
1719#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1720 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001721 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock) &&
1722 l4->si[0].conn->xprt_ctx &&
1723 SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02001724 return 1;
1725#else
1726 return 0;
1727#endif
1728}
1729
Willy Tarreau8d598402012-10-22 17:58:39 +02001730/* bin, returns serial in a binary chunk */
1731static int
1732smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1733 const struct arg *args, struct sample *smp)
1734{
1735 X509 *crt = NULL;
1736 int ret = 0;
1737 struct chunk *smp_trash;
1738
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001739 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001740 return 0;
1741
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001742 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001743 smp->flags |= SMP_F_MAY_CHANGE;
1744 return 0;
1745 }
1746
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001747 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001748 if (!crt)
1749 goto out;
1750
1751 smp_trash = sample_get_trash_chunk();
1752 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1753 goto out;
1754
1755 smp->data.str = *smp_trash;
1756 smp->type = SMP_T_BIN;
1757 ret = 1;
1758out:
1759 return ret;
1760}
Emeric Brunce5ad802012-10-22 14:11:22 +02001761/*str, returns notafter date in ASN1_UTCTIME format */
1762static int
1763smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1764 const struct arg *args, struct sample *smp)
1765{
1766 X509 *crt = NULL;
1767 int ret = 0;
1768 struct chunk *smp_trash;
1769
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001770 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001771 return 0;
1772
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001773 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001774 smp->flags |= SMP_F_MAY_CHANGE;
1775 return 0;
1776 }
1777
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001778 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001779 if (!crt)
1780 goto out;
1781
1782 smp_trash = sample_get_trash_chunk();
1783 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1784 goto out;
1785
1786 smp->data.str = *smp_trash;
1787 smp->type = SMP_T_STR;
1788 ret = 1;
1789out:
1790 return ret;
1791}
1792
1793/*str, returns notbefore date in ASN1_UTCTIME format */
1794static int
1795smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1796 const struct arg *args, struct sample *smp)
1797{
1798 X509 *crt = NULL;
1799 int ret = 0;
1800 struct chunk *smp_trash;
1801
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001802 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001803 return 0;
1804
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001805 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001806 smp->flags |= SMP_F_MAY_CHANGE;
1807 return 0;
1808 }
1809
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001810 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001811 if (!crt)
1812 goto out;
1813
1814 smp_trash = sample_get_trash_chunk();
1815 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1816 goto out;
1817
1818 smp->data.str = *smp_trash;
1819 smp->type = SMP_T_STR;
1820 ret = 1;
1821out:
1822 return ret;
1823}
Willy Tarreau8d598402012-10-22 17:58:39 +02001824
Emeric Bruna7359fd2012-10-17 15:03:11 +02001825/* integer, returns the frontend certificate version */
1826static int
1827smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1828 const struct arg *args, struct sample *smp)
1829{
1830 X509 *crt;
1831
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001832 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001833 return 0;
1834
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001835 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001836 smp->flags |= SMP_F_MAY_CHANGE;
1837 return 0;
1838 }
1839
1840 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001841 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001842 if (!crt)
1843 return 0;
1844
1845 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1846 smp->type = SMP_T_UINT;
1847
1848 return 1;
1849}
1850
Emeric Brun7f56e742012-10-19 18:15:40 +02001851/* str, returns the client certificate sig alg */
1852static int
1853smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1854 const struct arg *args, struct sample *smp)
1855{
1856 X509 *crt;
1857 int nid;
1858
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001859 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02001860 return 0;
1861
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001862 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02001863 smp->flags |= SMP_F_MAY_CHANGE;
1864 return 0;
1865 }
1866
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001867 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02001868 if (!crt)
1869 return 0;
1870
1871 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1872
1873 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1874 if (!smp->data.str.str)
1875 return 0;
1876
1877 smp->type = SMP_T_CSTR;
1878 smp->data.str.len = strlen(smp->data.str.str);
1879
1880 return 1;
1881}
1882
Emeric Brun521a0112012-10-22 12:22:55 +02001883/* str, returns the client certificate key alg */
1884static int
1885smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1886 const struct arg *args, struct sample *smp)
1887{
1888 X509 *crt;
1889 int nid;
1890
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001891 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02001892 return 0;
1893
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001894 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02001895 smp->flags |= SMP_F_MAY_CHANGE;
1896 return 0;
1897 }
1898
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001899 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02001900 if (!crt)
1901 return 0;
1902
1903 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1904
1905 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1906 if (!smp->data.str.str)
1907 return 0;
1908
1909 smp->type = SMP_T_CSTR;
1910 smp->data.str.len = strlen(smp->data.str.str);
1911
1912 return 1;
1913}
1914
Emeric Brun87855892012-10-17 17:39:35 +02001915/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1916static int
1917smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1918 const struct arg *args, struct sample *smp)
1919{
1920 X509 *crt = NULL;
1921 X509_NAME *name;
1922 int ret = 0;
1923 struct chunk *smp_trash;
1924
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001925 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001926 return 0;
1927
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001928 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001929 smp->flags |= SMP_F_MAY_CHANGE;
1930 return 0;
1931 }
1932
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001933 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001934 if (!crt)
1935 goto out;
1936
1937 name = X509_get_issuer_name(crt);
1938 if (!name)
1939 goto out;
1940
1941 smp_trash = sample_get_trash_chunk();
1942 if (args && args[0].type == ARGT_STR) {
1943 int pos = 1;
1944
1945 if (args[1].type == ARGT_SINT)
1946 pos = args[1].data.sint;
1947 else if (args[1].type == ARGT_UINT)
1948 pos =(int)args[1].data.uint;
1949
1950 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1951 goto out;
1952 }
1953 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1954 goto out;
1955
1956 smp->type = SMP_T_STR;
1957 smp->data.str = *smp_trash;
1958 ret = 1;
1959out:
1960 return ret;
1961}
1962
1963/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1964static int
1965smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1966 const struct arg *args, struct sample *smp)
1967{
1968 X509 *crt = NULL;
1969 X509_NAME *name;
1970 int ret = 0;
1971 struct chunk *smp_trash;
1972
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001973 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001974 return 0;
1975
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001976 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001977 smp->flags |= SMP_F_MAY_CHANGE;
1978 return 0;
1979 }
1980
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001981 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001982 if (!crt)
1983 goto out;
1984
1985 name = X509_get_subject_name(crt);
1986 if (!name)
1987 goto out;
1988
1989 smp_trash = sample_get_trash_chunk();
1990 if (args && args[0].type == ARGT_STR) {
1991 int pos = 1;
1992
1993 if (args[1].type == ARGT_SINT)
1994 pos = args[1].data.sint;
1995 else if (args[1].type == ARGT_UINT)
1996 pos =(int)args[1].data.uint;
1997
1998 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1999 goto out;
2000 }
2001 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2002 goto out;
2003
2004 smp->type = SMP_T_STR;
2005 smp->data.str = *smp_trash;
2006 ret = 1;
2007out:
2008 return ret;
2009}
2010
Emeric Brun589fcad2012-10-16 14:13:26 +02002011static int
2012smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2013 const struct arg *args, struct sample *smp)
2014{
2015 smp->flags = 0;
2016
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002017 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002018 return 0;
2019
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002020 smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002021 if (!smp->data.str.str)
2022 return 0;
2023
2024 smp->type = SMP_T_CSTR;
2025 smp->data.str.len = strlen(smp->data.str.str);
2026
2027 return 1;
2028}
2029
2030static int
2031smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2032 const struct arg *args, struct sample *smp)
2033{
2034 smp->flags = 0;
2035
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002036 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002037 return 0;
2038
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002039 if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
Emeric Brun589fcad2012-10-16 14:13:26 +02002040 return 0;
2041
2042 smp->type = SMP_T_UINT;
2043
2044 return 1;
2045}
2046
2047static int
2048smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2049 const struct arg *args, struct sample *smp)
2050{
2051 smp->flags = 0;
2052
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002053 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002054 return 0;
2055
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002056 smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002057 if (!smp->data.uint)
2058 return 0;
2059
2060 smp->type = SMP_T_UINT;
2061
2062 return 1;
2063}
2064
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002065#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002066static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002067smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2068 const struct arg *args, struct sample *smp)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002069{
Willy Tarreaua33c6542012-10-15 13:19:06 +02002070 smp->flags = 0;
2071 smp->type = SMP_T_CSTR;
2072
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002073 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002074 return 0;
2075
2076 smp->data.str.str = NULL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002077 SSL_get0_next_proto_negotiated(l4->si[0].conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002078 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2079
2080 if (!smp->data.str.str)
2081 return 0;
2082
2083 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002084}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002085#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002086
2087static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002088smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2089 const struct arg *args, struct sample *smp)
2090{
2091 smp->flags = 0;
2092
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002093 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002094 return 0;
2095
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002096 smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002097 if (!smp->data.str.str)
2098 return 0;
2099
2100 smp->type = SMP_T_CSTR;
2101 smp->data.str.len = strlen(smp->data.str.str);
2102
2103 return 1;
2104}
2105
2106static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002107smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2108 const struct arg *args, struct sample *smp)
2109{
2110#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2111 SSL_SESSION *sess;
2112
2113 smp->flags = 0;
2114 smp->type = SMP_T_CBIN;
2115
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002116 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunfe68f682012-10-16 14:59:28 +02002117 return 0;
2118
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002119 sess = SSL_get_session(l4->si[0].conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002120 if (!sess)
2121 return 0;
2122
2123 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2124 if (!smp->data.str.str || !&smp->data.str.len)
2125 return 0;
2126
2127 return 1;
2128#else
2129 return 0;
2130#endif
2131}
2132
2133static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002134smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2135 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02002136{
2137#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2138 smp->flags = 0;
2139 smp->type = SMP_T_CSTR;
2140
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002141 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau7875d092012-09-10 08:20:03 +02002142 return 0;
2143
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002144 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 +02002145 if (!smp->data.str.str)
2146 return 0;
2147
Willy Tarreau7875d092012-09-10 08:20:03 +02002148 smp->data.str.len = strlen(smp->data.str.str);
2149 return 1;
2150#else
2151 return 0;
2152#endif
2153}
2154
Emeric Brun2525b6b2012-10-18 15:59:43 +02002155/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002156static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002157smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002158 const struct arg *args, struct sample *smp)
2159{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002160 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002161 return 0;
2162
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002163 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002164 smp->flags = SMP_F_MAY_CHANGE;
2165 return 0;
2166 }
2167
2168 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002169 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002170 smp->flags = 0;
2171
2172 return 1;
2173}
2174
Emeric Brun2525b6b2012-10-18 15:59:43 +02002175/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002176static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002177smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002178 const struct arg *args, struct sample *smp)
2179{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002180 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002181 return 0;
2182
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002183 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002184 smp->flags = SMP_F_MAY_CHANGE;
2185 return 0;
2186 }
2187
2188 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002189 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002190 smp->flags = 0;
2191
2192 return 1;
2193}
2194
Emeric Brun2525b6b2012-10-18 15:59:43 +02002195/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002196static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002197smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2198 const struct arg *args, struct sample *smp)
Emeric Brunf282a812012-09-21 15:27:54 +02002199{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002200 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002201 return 0;
2202
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002203 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002204 smp->flags = SMP_F_MAY_CHANGE;
2205 return 0;
2206 }
2207
2208 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002209 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002210 smp->flags = 0;
2211
2212 return 1;
2213}
2214
Emeric Brun2525b6b2012-10-18 15:59:43 +02002215/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002216static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002217smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2218 const struct arg *args, struct sample *smp)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002219{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002220 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002221 return 0;
2222
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002223 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002224 smp->flags = SMP_F_MAY_CHANGE;
2225 return 0;
2226 }
2227
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002228 if (!l4->si[0].conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002229 return 0;
2230
2231 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002232 smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002233 smp->flags = 0;
2234
2235 return 1;
2236}
2237
Emeric Brunfb510ea2012-10-05 12:00:26 +02002238/* parse the "ca-file" bind keyword */
2239static 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 +02002240{
2241 if (!*args[cur_arg + 1]) {
2242 if (err)
2243 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2244 return ERR_ALERT | ERR_FATAL;
2245 }
2246
Emeric Brunef42d922012-10-11 16:11:36 +02002247 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2248 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2249 else
2250 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002251
Emeric Brund94b3fe2012-09-20 18:23:56 +02002252 return 0;
2253}
2254
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002255/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002256static 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 +02002257{
2258 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002259 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002260 return ERR_ALERT | ERR_FATAL;
2261 }
2262
Emeric Brun76d88952012-10-05 15:47:31 +02002263 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002264 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002265 return 0;
2266}
2267
2268/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002269static 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 +02002270{
Emeric Brunc8e8d122012-10-02 18:42:10 +02002271 char path[PATH_MAX];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002272 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002273 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002274 return ERR_ALERT | ERR_FATAL;
2275 }
2276
Emeric Brunc8e8d122012-10-02 18:42:10 +02002277 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
2278 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > PATH_MAX) {
2279 memprintf(err, "'%s' : path too long", args[cur_arg]);
2280 return ERR_ALERT | ERR_FATAL;
2281 }
2282 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2283 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2284 return ERR_ALERT | ERR_FATAL;
2285
2286 return 0;
2287 }
2288
Willy Tarreau4348fad2012-09-20 16:48:07 +02002289 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002290 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002291
2292 return 0;
2293}
2294
Emeric Brunfb510ea2012-10-05 12:00:26 +02002295/* parse the "crl-file" bind keyword */
2296static 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 +02002297{
Emeric Brun051cdab2012-10-02 19:25:50 +02002298#ifndef X509_V_FLAG_CRL_CHECK
2299 if (err)
2300 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2301 return ERR_ALERT | ERR_FATAL;
2302#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002303 if (!*args[cur_arg + 1]) {
2304 if (err)
2305 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2306 return ERR_ALERT | ERR_FATAL;
2307 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002308
Emeric Brunef42d922012-10-11 16:11:36 +02002309 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2310 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2311 else
2312 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002313
Emeric Brun2b58d042012-09-20 17:10:03 +02002314 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002315#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002316}
2317
2318/* parse the "ecdhe" bind keyword keywords */
2319static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2320{
2321#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2322 if (err)
2323 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2324 return ERR_ALERT | ERR_FATAL;
2325#elif defined(OPENSSL_NO_ECDH)
2326 if (err)
2327 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2328 return ERR_ALERT | ERR_FATAL;
2329#else
2330 if (!*args[cur_arg + 1]) {
2331 if (err)
2332 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2333 return ERR_ALERT | ERR_FATAL;
2334 }
2335
2336 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002337
2338 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002339#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002340}
2341
Emeric Brun81c00f02012-09-21 14:31:21 +02002342/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2343static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2344{
2345 int code;
2346 char *p = args[cur_arg + 1];
2347 unsigned long long *ignerr = &conf->crt_ignerr;
2348
2349 if (!*p) {
2350 if (err)
2351 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2352 return ERR_ALERT | ERR_FATAL;
2353 }
2354
2355 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2356 ignerr = &conf->ca_ignerr;
2357
2358 if (strcmp(p, "all") == 0) {
2359 *ignerr = ~0ULL;
2360 return 0;
2361 }
2362
2363 while (p) {
2364 code = atoi(p);
2365 if ((code <= 0) || (code > 63)) {
2366 if (err)
2367 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2368 args[cur_arg], code, args[cur_arg + 1]);
2369 return ERR_ALERT | ERR_FATAL;
2370 }
2371 *ignerr |= 1ULL << code;
2372 p = strchr(p, ',');
2373 if (p)
2374 p++;
2375 }
2376
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002377 return 0;
2378}
2379
2380/* parse the "force-sslv3" bind keyword */
2381static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2382{
2383 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2384 return 0;
2385}
2386
2387/* parse the "force-tlsv10" bind keyword */
2388static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2389{
2390 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002391 return 0;
2392}
2393
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002394/* parse the "force-tlsv11" bind keyword */
2395static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2396{
2397#if SSL_OP_NO_TLSv1_1
2398 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
2399 return 0;
2400#else
2401 if (err)
2402 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
2403 return ERR_ALERT | ERR_FATAL;
2404#endif
2405}
2406
2407/* parse the "force-tlsv12" bind keyword */
2408static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2409{
2410#if SSL_OP_NO_TLSv1_2
2411 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
2412 return 0;
2413#else
2414 if (err)
2415 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
2416 return ERR_ALERT | ERR_FATAL;
2417#endif
2418}
2419
2420
Emeric Brun2d0c4822012-10-02 13:45:20 +02002421/* parse the "no-tls-tickets" bind keyword */
2422static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2423{
Emeric Brun89675492012-10-05 13:48:26 +02002424 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02002425 return 0;
2426}
2427
Emeric Brun2d0c4822012-10-02 13:45:20 +02002428
Emeric Brun9b3009b2012-10-05 11:55:06 +02002429/* parse the "no-sslv3" bind keyword */
2430static 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 +02002431{
Emeric Brun89675492012-10-05 13:48:26 +02002432 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002433 return 0;
2434}
2435
Emeric Brun9b3009b2012-10-05 11:55:06 +02002436/* parse the "no-tlsv10" bind keyword */
2437static 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 +02002438{
Emeric Brun89675492012-10-05 13:48:26 +02002439 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002440 return 0;
2441}
2442
Emeric Brun9b3009b2012-10-05 11:55:06 +02002443/* parse the "no-tlsv11" bind keyword */
2444static 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 +02002445{
Emeric Brun89675492012-10-05 13:48:26 +02002446 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002447 return 0;
2448}
2449
Emeric Brun9b3009b2012-10-05 11:55:06 +02002450/* parse the "no-tlsv12" bind keyword */
2451static 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 +02002452{
Emeric Brun89675492012-10-05 13:48:26 +02002453 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002454 return 0;
2455}
2456
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002457/* parse the "npn" bind keyword */
2458static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2459{
2460#ifdef OPENSSL_NPN_NEGOTIATED
2461 char *p1, *p2;
2462
2463 if (!*args[cur_arg + 1]) {
2464 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
2465 return ERR_ALERT | ERR_FATAL;
2466 }
2467
2468 free(conf->npn_str);
2469
2470 /* the NPN string is built as a suite of (<len> <name>)* */
2471 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
2472 conf->npn_str = calloc(1, conf->npn_len);
2473 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
2474
2475 /* replace commas with the name length */
2476 p1 = conf->npn_str;
2477 p2 = p1 + 1;
2478 while (1) {
2479 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
2480 if (!p2)
2481 p2 = p1 + 1 + strlen(p1 + 1);
2482
2483 if (p2 - (p1 + 1) > 255) {
2484 *p2 = '\0';
2485 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2486 return ERR_ALERT | ERR_FATAL;
2487 }
2488
2489 *p1 = p2 - (p1 + 1);
2490 p1 = p2;
2491
2492 if (!*p2)
2493 break;
2494
2495 *(p2++) = '\0';
2496 }
2497 return 0;
2498#else
2499 if (err)
2500 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
2501 return ERR_ALERT | ERR_FATAL;
2502#endif
2503}
2504
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002505/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002506static 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 +02002507{
Willy Tarreau81796be2012-09-22 19:11:47 +02002508 struct listener *l;
2509
Willy Tarreau4348fad2012-09-20 16:48:07 +02002510 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02002511
2512 if (global.listen_default_ciphers && !conf->ciphers)
2513 conf->ciphers = strdup(global.listen_default_ciphers);
2514
Willy Tarreau81796be2012-09-22 19:11:47 +02002515 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002516 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02002517
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002518 return 0;
2519}
2520
Emeric Brund94b3fe2012-09-20 18:23:56 +02002521/* parse the "verify" bind keyword */
2522static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2523{
2524 if (!*args[cur_arg + 1]) {
2525 if (err)
2526 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
2527 return ERR_ALERT | ERR_FATAL;
2528 }
2529
2530 if (strcmp(args[cur_arg + 1], "none") == 0)
2531 conf->verify = SSL_VERIFY_NONE;
2532 else if (strcmp(args[cur_arg + 1], "optional") == 0)
2533 conf->verify = SSL_VERIFY_PEER;
2534 else if (strcmp(args[cur_arg + 1], "required") == 0)
2535 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2536 else {
2537 if (err)
2538 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
2539 args[cur_arg], args[cur_arg + 1]);
2540 return ERR_ALERT | ERR_FATAL;
2541 }
2542
2543 return 0;
2544}
2545
Willy Tarreau92faadf2012-10-10 23:04:25 +02002546/************** "server" keywords ****************/
2547
Emeric Brunef42d922012-10-11 16:11:36 +02002548/* parse the "ca-file" server keyword */
2549static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2550{
2551 if (!*args[*cur_arg + 1]) {
2552 if (err)
2553 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
2554 return ERR_ALERT | ERR_FATAL;
2555 }
2556
2557 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2558 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2559 else
2560 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
2561
2562 return 0;
2563}
2564
Willy Tarreau92faadf2012-10-10 23:04:25 +02002565/* parse the "check-ssl" server keyword */
2566static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2567{
2568 newsrv->check.use_ssl = 1;
2569 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2570 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2571 return 0;
2572}
2573
2574/* parse the "ciphers" server keyword */
2575static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2576{
2577 if (!*args[*cur_arg + 1]) {
2578 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
2579 return ERR_ALERT | ERR_FATAL;
2580 }
2581
2582 free(newsrv->ssl_ctx.ciphers);
2583 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
2584 return 0;
2585}
2586
Emeric Brunef42d922012-10-11 16:11:36 +02002587/* parse the "crl-file" server keyword */
2588static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2589{
2590#ifndef X509_V_FLAG_CRL_CHECK
2591 if (err)
2592 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
2593 return ERR_ALERT | ERR_FATAL;
2594#else
2595 if (!*args[*cur_arg + 1]) {
2596 if (err)
2597 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
2598 return ERR_ALERT | ERR_FATAL;
2599 }
2600
2601 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2602 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2603 else
2604 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
2605
2606 return 0;
2607#endif
2608}
2609
Emeric Bruna7aa3092012-10-26 12:58:00 +02002610/* parse the "crt" server keyword */
2611static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2612{
2613 if (!*args[*cur_arg + 1]) {
2614 if (err)
2615 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
2616 return ERR_ALERT | ERR_FATAL;
2617 }
2618
2619 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
2620 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2621 else
2622 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
2623
2624 return 0;
2625}
Emeric Brunef42d922012-10-11 16:11:36 +02002626
Willy Tarreau92faadf2012-10-10 23:04:25 +02002627/* parse the "force-sslv3" server keyword */
2628static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2629{
2630 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
2631 return 0;
2632}
2633
2634/* parse the "force-tlsv10" server keyword */
2635static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2636{
2637 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
2638 return 0;
2639}
2640
2641/* parse the "force-tlsv11" server keyword */
2642static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2643{
2644#if SSL_OP_NO_TLSv1_1
2645 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
2646 return 0;
2647#else
2648 if (err)
2649 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
2650 return ERR_ALERT | ERR_FATAL;
2651#endif
2652}
2653
2654/* parse the "force-tlsv12" server keyword */
2655static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2656{
2657#if SSL_OP_NO_TLSv1_2
2658 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
2659 return 0;
2660#else
2661 if (err)
2662 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
2663 return ERR_ALERT | ERR_FATAL;
2664#endif
2665}
2666
2667/* parse the "no-sslv3" server keyword */
2668static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2669{
2670 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
2671 return 0;
2672}
2673
2674/* parse the "no-tlsv10" server keyword */
2675static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2676{
2677 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
2678 return 0;
2679}
2680
2681/* parse the "no-tlsv11" server keyword */
2682static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2683{
2684 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
2685 return 0;
2686}
2687
2688/* parse the "no-tlsv12" server keyword */
2689static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2690{
2691 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
2692 return 0;
2693}
2694
Emeric Brunf9c5c472012-10-11 15:28:34 +02002695/* parse the "no-tls-tickets" server keyword */
2696static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2697{
2698 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
2699 return 0;
2700}
2701
Willy Tarreau92faadf2012-10-10 23:04:25 +02002702/* parse the "ssl" server keyword */
2703static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2704{
2705 newsrv->use_ssl = 1;
2706 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2707 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2708 return 0;
2709}
2710
Emeric Brunef42d922012-10-11 16:11:36 +02002711/* parse the "verify" server keyword */
2712static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2713{
2714 if (!*args[*cur_arg + 1]) {
2715 if (err)
2716 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
2717 return ERR_ALERT | ERR_FATAL;
2718 }
2719
2720 if (strcmp(args[*cur_arg + 1], "none") == 0)
2721 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
2722 else if (strcmp(args[*cur_arg + 1], "required") == 0)
2723 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
2724 else {
2725 if (err)
2726 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
2727 args[*cur_arg], args[*cur_arg + 1]);
2728 return ERR_ALERT | ERR_FATAL;
2729 }
2730
2731 return 0;
2732}
2733
Willy Tarreau7875d092012-09-10 08:20:03 +02002734/* 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 sample_fetch_kw_list sample_fetch_keywords = {{ },{
Emeric Brun2525b6b2012-10-18 15:59:43 +02002738 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2739 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2740 { "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 +02002741 { "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 +02002742 { "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 +02002743 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
2744 { "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 +02002745 { "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 +02002746 { "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 +02002747 { "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 +02002748 { "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 +02002749 { "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 +02002750 { "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 +02002751 { "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 +02002752 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
2753 { "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 +02002754 { "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 +02002755 { "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 +02002756 { "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 +02002757 { "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 +02002758 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun589fcad2012-10-16 14:13:26 +02002759 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2760 { "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 +02002761 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
2762 { "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 +02002763#ifdef OPENSSL_NPN_NEGOTIATED
Emeric Brun2525b6b2012-10-18 15:59:43 +02002764 { "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 +02002765#endif
Emeric Brun589fcad2012-10-16 14:13:26 +02002766 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
2767 { "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 +02002768 { "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 +02002769 { "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 +02002770 { NULL, NULL, 0, 0, 0 },
2771}};
2772
2773/* Note: must not be declared <const> as its list will be overwritten.
2774 * Please take care of keeping this list alphabetically sorted.
2775 */
2776static struct acl_kw_list acl_kws = {{ },{
Emeric Brun2525b6b2012-10-18 15:59:43 +02002777 { "ssl_c_ca_err", acl_parse_int, smp_fetch_ssl_c_ca_err, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2778 { "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 },
2779 { "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 +02002780 { "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 +02002781 { "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 +02002782 { "ssl_c_notafter", acl_parse_str, smp_fetch_ssl_c_notafter, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2783 { "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 +02002784 { "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 +02002785 { "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 +02002786 { "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 +02002787 { "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 +02002788 { "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 +02002789 { "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 +02002790 { "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 +02002791 { "ssl_f_notafter", acl_parse_str, smp_fetch_ssl_f_notafter, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2792 { "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 +02002793 { "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 +02002794 { "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 +02002795 { "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 +02002796 { "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 +02002797 { "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 +02002798 { "ssl_fc_alg_keysize", acl_parse_str, smp_fetch_ssl_fc_alg_keysize, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2799 { "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 +02002800 { "ssl_fc_has_crt", acl_parse_int, smp_fetch_ssl_fc_has_crt, acl_match_nothing, ACL_USE_L6REQ_PERMANENT, 0 },
2801 { "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 +02002802#ifdef OPENSSL_NPN_NEGOTIATED
Emeric Brun2525b6b2012-10-18 15:59:43 +02002803 { "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 +02002804#endif
Emeric Brun589fcad2012-10-16 14:13:26 +02002805 { "ssl_fc_protocol", acl_parse_str, smp_fetch_ssl_fc_protocol, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2806 { "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 +02002807 { "ssl_fc_sni", acl_parse_str, smp_fetch_ssl_fc_sni, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2808 { "ssl_fc_sni_end", acl_parse_str, smp_fetch_ssl_fc_sni, acl_match_end, ACL_USE_L6REQ_PERMANENT, 0 },
2809 { "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 +02002810 { NULL, NULL, NULL, NULL },
2811}};
2812
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002813/* Note: must not be declared <const> as its list will be overwritten.
2814 * Please take care of keeping this list alphabetically sorted, doing so helps
2815 * all code contributors.
2816 * Optional keywords are also declared with a NULL ->parse() function so that
2817 * the config parser can report an appropriate error when a known keyword was
2818 * not enabled.
2819 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02002820static struct bind_kw_list bind_kws = { "SSL", { }, {
Emeric Brunfb510ea2012-10-05 12:00:26 +02002821 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002822 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
2823 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02002824 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002825 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
2826 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
2827 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002828 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
2829 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
2830 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
2831 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02002832 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
2833 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
2834 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
2835 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002836 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002837 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
2838 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002839 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002840 { NULL, NULL, 0 },
2841}};
Emeric Brun46591952012-05-18 15:47:34 +02002842
Willy Tarreau92faadf2012-10-10 23:04:25 +02002843/* Note: must not be declared <const> as its list will be overwritten.
2844 * Please take care of keeping this list alphabetically sorted, doing so helps
2845 * all code contributors.
2846 * Optional keywords are also declared with a NULL ->parse() function so that
2847 * the config parser can report an appropriate error when a known keyword was
2848 * not enabled.
2849 */
2850static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02002851 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002852 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
2853 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02002854 { "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 +02002855 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002856 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
2857 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
2858 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
2859 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
2860 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
2861 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
2862 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
2863 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02002864 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002865 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02002866 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Willy Tarreau92faadf2012-10-10 23:04:25 +02002867 { NULL, NULL, 0, 0 },
2868}};
2869
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002870/* transport-layer operations for SSL sockets */
2871struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02002872 .snd_buf = ssl_sock_from_buf,
2873 .rcv_buf = ssl_sock_to_buf,
2874 .rcv_pipe = NULL,
2875 .snd_pipe = NULL,
2876 .shutr = NULL,
2877 .shutw = ssl_sock_shutw,
2878 .close = ssl_sock_close,
2879 .init = ssl_sock_init,
2880};
2881
2882__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02002883static void __ssl_sock_init(void)
2884{
Emeric Brun46591952012-05-18 15:47:34 +02002885 STACK_OF(SSL_COMP)* cm;
2886
2887 SSL_library_init();
2888 cm = SSL_COMP_get_compression_methods();
2889 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02002890 sample_register_fetches(&sample_fetch_keywords);
2891 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002892 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02002893 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02002894}
2895
2896/*
2897 * Local variables:
2898 * c-indent-level: 8
2899 * c-basic-offset: 8
2900 * End:
2901 */