blob: 87eff2b7c41aba1c71baba1a6ed55f82b1b16d12 [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 */
Emeric Brun644cde02012-12-14 11:21:13 +0100235
236 /* Clear openssl global errors stack */
237 ERR_clear_error();
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200238end:
239 if (dh)
240 DH_free(dh);
241
242 if (in)
243 BIO_free(in);
244
245 return ret;
246}
247#endif
248
Emeric Brunfc0421f2012-09-07 17:30:07 +0200249/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
250 * an early error happens and the caller must call SSL_CTX_free() by itelf.
251 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200252int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200253{
254 BIO *in;
255 X509 *x = NULL, *ca;
256 int i, len, err;
257 int ret = -1;
258 int order = 0;
259 X509_NAME *xname;
260 char *str;
261 struct sni_ctx *sc;
262#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
263 STACK_OF(GENERAL_NAME) *names;
264#endif
265
266 in = BIO_new(BIO_s_file());
267 if (in == NULL)
268 goto end;
269
270 if (BIO_read_filename(in, file) <= 0)
271 goto end;
272
273 x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
274 if (x == NULL)
275 goto end;
276
277#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
278 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
279 if (names) {
280 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
281 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
282 if (name->type == GEN_DNS) {
283 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
284 if ((len = strlen(str))) {
285 int j;
286
287 if (*str != '*') {
288 sc = malloc(sizeof(struct sni_ctx) + len + 1);
289 for (j = 0; j < len; j++)
290 sc->name.key[j] = tolower(str[j]);
291 sc->name.key[len] = 0;
292 sc->order = order++;
293 sc->ctx = ctx;
294 ebst_insert(&s->sni_ctx, &sc->name);
295 }
296 else {
297 sc = malloc(sizeof(struct sni_ctx) + len);
298 for (j = 1; j < len; j++)
299 sc->name.key[j-1] = tolower(str[j]);
300 sc->name.key[len-1] = 0;
301 sc->order = order++;
302 sc->ctx = ctx;
303 ebst_insert(&s->sni_w_ctx, &sc->name);
304 }
305 }
306 OPENSSL_free(str);
307 }
308 }
309 }
310 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
311 }
312#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
313
314 xname = X509_get_subject_name(x);
315 i = -1;
316 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
317 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
318 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
319 if ((len = strlen(str))) {
320 int j;
321
322 if (*str != '*') {
323 sc = malloc(sizeof(struct sni_ctx) + len + 1);
324 for (j = 0; j < len; j++)
325 sc->name.key[j] = tolower(str[j]);
326 sc->name.key[len] = 0;
327 sc->order = order++;
328 sc->ctx = ctx;
329 ebst_insert(&s->sni_ctx, &sc->name);
330 }
331 else {
332 sc = malloc(sizeof(struct sni_ctx) + len);
333 for (j = 1; j < len; j++)
334 sc->name.key[j-1] = tolower(str[j]);
335 sc->name.key[len-1] = 0;
336 sc->order = order++;
337 sc->ctx = ctx;
338 ebst_insert(&s->sni_w_ctx, &sc->name);
339 }
340 }
341 OPENSSL_free(str);
342 }
343 }
344
345 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
346 if (!SSL_CTX_use_certificate(ctx, x))
347 goto end;
348
349 if (ctx->extra_certs != NULL) {
350 sk_X509_pop_free(ctx->extra_certs, X509_free);
351 ctx->extra_certs = NULL;
352 }
353
354 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata))) {
355 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
356 X509_free(ca);
357 goto end;
358 }
359 }
360
361 err = ERR_get_error();
362 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
363 /* we successfully reached the last cert in the file */
364 ret = 1;
365 }
366 ERR_clear_error();
367
368end:
369 if (x)
370 X509_free(x);
371
372 if (in)
373 BIO_free(in);
374
375 return ret;
376}
377
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200378static 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 +0200379{
380 int ret;
381 SSL_CTX *ctx;
382
383 ctx = SSL_CTX_new(SSLv23_server_method());
384 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200385 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
386 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200387 return 1;
388 }
389
390 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200391 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
392 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200393 SSL_CTX_free(ctx);
394 return 1;
395 }
396
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200397 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200398 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200399 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
400 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200401 if (ret < 0) /* serious error, must do that ourselves */
402 SSL_CTX_free(ctx);
403 return 1;
404 }
Emeric Brun61694ab2012-10-26 13:35:33 +0200405
406 if (SSL_CTX_check_private_key(ctx) <= 0) {
407 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
408 err && *err ? *err : "", path);
409 return 1;
410 }
411
Emeric Brunfc0421f2012-09-07 17:30:07 +0200412 /* we must not free the SSL_CTX anymore below, since it's already in
413 * the tree, so it will be discovered and cleaned in time.
414 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200415#ifndef OPENSSL_NO_DH
416 ret = ssl_sock_load_dh_params(ctx, path);
417 if (ret < 0) {
418 if (err)
419 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
420 *err ? *err : "", path);
421 return 1;
422 }
423#endif
424
Emeric Brunfc0421f2012-09-07 17:30:07 +0200425#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200426 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200427 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
428 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +0200429 return 1;
430 }
431#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200432 if (!bind_conf->default_ctx)
433 bind_conf->default_ctx = ctx;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200434
435 return 0;
436}
437
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200438int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200439{
440 struct dirent *de;
441 DIR *dir;
442 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +0100443 char *end;
444 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200445 int cfgerr = 0;
446
447 if (!(dir = opendir(path)))
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200448 return ssl_sock_load_cert_file(path, bind_conf, curproxy, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200449
450 /* strip trailing slashes, including first one */
451 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
452 *end = 0;
453
Emeric Brunfc0421f2012-09-07 17:30:07 +0200454 while ((de = readdir(dir))) {
Willy Tarreauee2663b2012-12-06 11:36:59 +0100455 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200456 if (stat(fp, &buf) != 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200457 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
458 err && *err ? *err : "", fp, strerror(errno));
Emeric Brunfc0421f2012-09-07 17:30:07 +0200459 cfgerr++;
460 continue;
461 }
462 if (!S_ISREG(buf.st_mode))
463 continue;
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200464 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, curproxy, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200465 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200466 closedir(dir);
467 return cfgerr;
468}
469
470#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
471#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
472#endif
473
474#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
475#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
Willy Tarreau7d588ee2012-11-26 18:47:31 +0100476#define SSL_renegotiate_pending(arg) 0
Emeric Brunfc0421f2012-09-07 17:30:07 +0200477#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200478#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
479#define SSL_OP_SINGLE_ECDH_USE 0
480#endif
Emeric Brun2d0c4822012-10-02 13:45:20 +0200481#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
482#define SSL_OP_NO_TICKET 0
483#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200484#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
485#define SSL_OP_NO_COMPRESSION 0
486#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +0200487#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
488#define SSL_OP_NO_TLSv1_1 0
489#endif
490#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
491#define SSL_OP_NO_TLSv1_2 0
492#endif
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200493#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
494#define SSL_OP_SINGLE_DH_USE 0
495#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200496#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
497#define SSL_OP_SINGLE_ECDH_USE 0
498#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200499#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
500#define SSL_MODE_RELEASE_BUFFERS 0
501#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200502int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy *curproxy)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200503{
504 int cfgerr = 0;
505 int ssloptions =
506 SSL_OP_ALL | /* all known workarounds for bugs */
507 SSL_OP_NO_SSLv2 |
508 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200509 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +0200510 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +0200511 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
512 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200513 int sslmode =
514 SSL_MODE_ENABLE_PARTIAL_WRITE |
515 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
516 SSL_MODE_RELEASE_BUFFERS;
517
Emeric Brun89675492012-10-05 13:48:26 +0200518 if (bind_conf->ssl_options & BC_SSL_O_NO_SSLV3)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200519 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brun89675492012-10-05 13:48:26 +0200520 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV10)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200521 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun89675492012-10-05 13:48:26 +0200522 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV11)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200523 ssloptions |= SSL_OP_NO_TLSv1_1;
Emeric Brun89675492012-10-05 13:48:26 +0200524 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV12)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200525 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun89675492012-10-05 13:48:26 +0200526 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
Emeric Brun2d0c4822012-10-02 13:45:20 +0200527 ssloptions |= SSL_OP_NO_TICKET;
Emeric Brun2cb7ae52012-10-05 14:14:21 +0200528 if (bind_conf->ssl_options & BC_SSL_O_USE_SSLV3)
529 SSL_CTX_set_ssl_version(ctx, SSLv3_server_method());
530 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV10)
531 SSL_CTX_set_ssl_version(ctx, TLSv1_server_method());
532#if SSL_OP_NO_TLSv1_1
533 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV11)
534 SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method());
535#endif
536#if SSL_OP_NO_TLSv1_2
537 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV12)
538 SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method());
539#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200540
541 SSL_CTX_set_options(ctx, ssloptions);
542 SSL_CTX_set_mode(ctx, sslmode);
Emeric Brune64aef12012-09-21 13:15:06 +0200543 SSL_CTX_set_verify(ctx, bind_conf->verify ? bind_conf->verify : SSL_VERIFY_NONE, ssl_sock_verifycbk);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200544 if (bind_conf->verify & SSL_VERIFY_PEER) {
Emeric Brunfb510ea2012-10-05 12:00:26 +0200545 if (bind_conf->ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200546 /* load CAfile to verify */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200547 if (!SSL_CTX_load_verify_locations(ctx, bind_conf->ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200548 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200549 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200550 cfgerr++;
551 }
552 /* set CA names fo client cert request, function returns void */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200553 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(bind_conf->ca_file));
Emeric Brund94b3fe2012-09-20 18:23:56 +0200554 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200555#ifdef X509_V_FLAG_CRL_CHECK
Emeric Brunfb510ea2012-10-05 12:00:26 +0200556 if (bind_conf->crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200557 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
558
Emeric Brunfb510ea2012-10-05 12:00:26 +0200559 if (!store || !X509_STORE_load_locations(store, bind_conf->crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200560 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200561 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200562 cfgerr++;
563 }
Emeric Brun561e5742012-10-02 15:20:55 +0200564 else {
565 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
566 }
Emeric Brund94b3fe2012-09-20 18:23:56 +0200567 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200568#endif
Emeric Brun644cde02012-12-14 11:21:13 +0100569 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +0200570 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200571
Emeric Brun4f65bff2012-11-16 15:11:00 +0100572 if (global.tune.ssllifetime)
573 SSL_CTX_set_timeout(ctx, global.tune.ssllifetime);
574
Emeric Brunfc0421f2012-09-07 17:30:07 +0200575 shared_context_set_cache(ctx);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200576 if (bind_conf->ciphers &&
577 !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200578 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 +0200579 curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200580 cfgerr++;
581 }
582
583 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200584#ifdef OPENSSL_NPN_NEGOTIATED
585 if (bind_conf->npn_str)
586 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
587#endif
588
Emeric Brunfc0421f2012-09-07 17:30:07 +0200589#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
590 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200591 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200592#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200593#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
594 if (bind_conf->ecdhe) {
595 int i;
596 EC_KEY *ecdh;
597
598 i = OBJ_sn2nid(bind_conf->ecdhe);
599 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
600 Alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
601 curproxy->id, bind_conf->ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
602 cfgerr++;
603 }
604 else {
605 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
606 EC_KEY_free(ecdh);
607 }
608 }
609#endif
610
Emeric Brunfc0421f2012-09-07 17:30:07 +0200611 return cfgerr;
612}
613
Emeric Brun94324a42012-10-11 14:00:19 +0200614/* prepare ssl context from servers options. Returns an error count */
615int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
616{
617 int cfgerr = 0;
618 int options =
619 SSL_OP_ALL | /* all known workarounds for bugs */
620 SSL_OP_NO_SSLv2 |
621 SSL_OP_NO_COMPRESSION;
622 int mode =
623 SSL_MODE_ENABLE_PARTIAL_WRITE |
624 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
625 SSL_MODE_RELEASE_BUFFERS;
626
627 /* Initiate SSL context for current server */
628 srv->ssl_ctx.reused_sess = NULL;
629 if (srv->use_ssl)
630 srv->xprt = &ssl_sock;
631 if (srv->check.use_ssl)
632 srv->check.xprt = &ssl_sock;
633
634 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
635 if (!srv->ssl_ctx.ctx) {
636 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
637 proxy_type_str(curproxy), curproxy->id,
638 srv->id);
639 cfgerr++;
640 return cfgerr;
641 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200642 if (srv->ssl_ctx.client_crt) {
643 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
644 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
645 proxy_type_str(curproxy), curproxy->id,
646 srv->id, srv->ssl_ctx.client_crt);
647 cfgerr++;
648 }
649 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
650 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
651 proxy_type_str(curproxy), curproxy->id,
652 srv->id, srv->ssl_ctx.client_crt);
653 cfgerr++;
654 }
655 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
656 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
657 proxy_type_str(curproxy), curproxy->id,
658 srv->id, srv->ssl_ctx.client_crt);
659 cfgerr++;
660 }
661 }
Emeric Brun94324a42012-10-11 14:00:19 +0200662
663 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
664 options |= SSL_OP_NO_SSLv3;
665 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
666 options |= SSL_OP_NO_TLSv1;
667 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
668 options |= SSL_OP_NO_TLSv1_1;
669 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
670 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200671 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
672 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200673 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
674 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
675 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
676 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
677#if SSL_OP_NO_TLSv1_1
678 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
679 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
680#endif
681#if SSL_OP_NO_TLSv1_2
682 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
683 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
684#endif
685
686 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
687 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Emeric Brunef42d922012-10-11 16:11:36 +0200688 SSL_CTX_set_verify(srv->ssl_ctx.ctx, srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE, NULL);
689 if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
690 if (srv->ssl_ctx.ca_file) {
691 /* load CAfile to verify */
692 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
693 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
694 curproxy->id, srv->id,
695 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
696 cfgerr++;
697 }
698 }
699#ifdef X509_V_FLAG_CRL_CHECK
700 if (srv->ssl_ctx.crl_file) {
701 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
702
703 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
704 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
705 curproxy->id, srv->id,
706 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
707 cfgerr++;
708 }
709 else {
710 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
711 }
712 }
713#endif
714 }
715
Emeric Brun4f65bff2012-11-16 15:11:00 +0100716 if (global.tune.ssllifetime)
717 SSL_CTX_set_timeout(srv->ssl_ctx.ctx, global.tune.ssllifetime);
718
Emeric Brun94324a42012-10-11 14:00:19 +0200719 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
720 if (srv->ssl_ctx.ciphers &&
721 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
722 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
723 curproxy->id, srv->id,
724 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
725 cfgerr++;
726 }
727
728 return cfgerr;
729}
730
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200731/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200732 * be NULL, in which case nothing is done. Returns the number of errors
733 * encountered.
734 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200735int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200736{
737 struct ebmb_node *node;
738 struct sni_ctx *sni;
739 int err = 0;
740
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200741 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200742 return 0;
743
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200744 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200745 while (node) {
746 sni = ebmb_entry(node, struct sni_ctx, name);
747 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200748 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200749 node = ebmb_next(node);
750 }
751
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200752 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200753 while (node) {
754 sni = ebmb_entry(node, struct sni_ctx, name);
755 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200756 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200757 node = ebmb_next(node);
758 }
759 return err;
760}
761
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200762/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200763 * be NULL, in which case nothing is done. The default_ctx is nullified too.
764 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200765void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200766{
767 struct ebmb_node *node, *back;
768 struct sni_ctx *sni;
769
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200770 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200771 return;
772
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200773 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200774 while (node) {
775 sni = ebmb_entry(node, struct sni_ctx, name);
776 back = ebmb_next(node);
777 ebmb_delete(node);
778 if (!sni->order) /* only free the CTX on its first occurrence */
779 SSL_CTX_free(sni->ctx);
780 free(sni);
781 node = back;
782 }
783
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200784 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200785 while (node) {
786 sni = ebmb_entry(node, struct sni_ctx, name);
787 back = ebmb_next(node);
788 ebmb_delete(node);
789 if (!sni->order) /* only free the CTX on its first occurrence */
790 SSL_CTX_free(sni->ctx);
791 free(sni);
792 node = back;
793 }
794
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200795 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +0200796}
797
Emeric Brun46591952012-05-18 15:47:34 +0200798/*
799 * This function is called if SSL * context is not yet allocated. The function
800 * is designed to be called before any other data-layer operation and sets the
801 * handshake flag on the connection. It is safe to call it multiple times.
802 * It returns 0 on success and -1 in error case.
803 */
804static int ssl_sock_init(struct connection *conn)
805{
806 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200807 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200808 return 0;
809
Willy Tarreau20879a02012-12-03 16:32:10 +0100810 if (global.maxsslconn && sslconns >= global.maxsslconn) {
811 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +0200812 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100813 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200814
Emeric Brun46591952012-05-18 15:47:34 +0200815 /* If it is in client mode initiate SSL session
816 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100817 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200818 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100819 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +0100820 if (!conn->xprt_ctx) {
821 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +0200822 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100823 }
Emeric Brun46591952012-05-18 15:47:34 +0200824
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200825 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100826 if (objt_server(conn->target)->ssl_ctx.reused_sess)
827 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +0200828
829 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200830 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200831
832 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200833 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200834
835 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200836 return 0;
837 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100838 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200839 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100840 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +0100841 if (!conn->xprt_ctx) {
842 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +0200843 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100844 }
Emeric Brun46591952012-05-18 15:47:34 +0200845
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200846 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200847
848 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200849 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200850
Emeric Brune1f38db2012-09-03 20:36:47 +0200851 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200852 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +0200853
Emeric Brun46591952012-05-18 15:47:34 +0200854 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200855 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200856
857 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200858 return 0;
859 }
860 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +0100861 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +0200862 return -1;
863}
864
865
866/* This is the callback which is used when an SSL handshake is pending. It
867 * updates the FD status if it wants some polling before being called again.
868 * It returns 0 if it fails in a fatal way or needs to poll to go further,
869 * otherwise it returns non-zero and removes itself from the connection's
870 * flags (the bit is provided in <flag> by the caller).
871 */
872int ssl_sock_handshake(struct connection *conn, unsigned int flag)
873{
874 int ret;
875
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200876 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200877 goto out_error;
878
Emeric Brun674b7432012-11-08 19:21:55 +0100879 /* If we use SSL_do_handshake to process a reneg initiated by
880 * the remote peer, it sometimes returns SSL_ERROR_SSL.
881 * Usually SSL_write and SSL_read are used and process implicitly
882 * the reneg handshake.
883 * Here we use SSL_peek as a workaround for reneg.
884 */
885 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
886 char c;
887
888 ret = SSL_peek(conn->xprt_ctx, &c, 1);
889 if (ret <= 0) {
890 /* handshake may have not been completed, let's find why */
891 ret = SSL_get_error(conn->xprt_ctx, ret);
892 if (ret == SSL_ERROR_WANT_WRITE) {
893 /* SSL handshake needs to write, L4 connection may not be ready */
894 __conn_sock_stop_recv(conn);
895 __conn_sock_poll_send(conn);
896 return 0;
897 }
898 else if (ret == SSL_ERROR_WANT_READ) {
899 /* handshake may have been completed but we have
900 * no more data to read.
901 */
902 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
903 ret = 1;
904 goto reneg_ok;
905 }
906 /* SSL handshake needs to read, L4 connection is ready */
907 if (conn->flags & CO_FL_WAIT_L4_CONN)
908 conn->flags &= ~CO_FL_WAIT_L4_CONN;
909 __conn_sock_stop_send(conn);
910 __conn_sock_poll_recv(conn);
911 return 0;
912 }
913 else if (ret == SSL_ERROR_SYSCALL) {
914 /* if errno is null, then connection was successfully established */
915 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
916 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +0100917 if (!conn->err_code) {
918 if (!((SSL *)conn->xprt_ctx)->packet_length)
919 if (!errno)
920 conn->err_code = CO_ER_SSL_EMPTY;
921 else
922 conn->err_code = CO_ER_SSL_ABORT;
923 else
924 conn->err_code = CO_ER_SSL_HANDSHAKE;
925 }
Emeric Brun674b7432012-11-08 19:21:55 +0100926 goto out_error;
927 }
928 else {
929 /* Fail on all other handshake errors */
930 /* Note: OpenSSL may leave unread bytes in the socket's
931 * buffer, causing an RST to be emitted upon close() on
932 * TCP sockets. We first try to drain possibly pending
933 * data to avoid this as much as possible.
934 */
935 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Willy Tarreau20879a02012-12-03 16:32:10 +0100936 if (!conn->err_code)
937 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +0100938 goto out_error;
939 }
940 }
941 /* read some data: consider handshake completed */
942 goto reneg_ok;
943 }
944
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200945 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200946 if (ret != 1) {
947 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200948 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +0200949
950 if (ret == SSL_ERROR_WANT_WRITE) {
951 /* SSL handshake needs to write, L4 connection may not be ready */
952 __conn_sock_stop_recv(conn);
953 __conn_sock_poll_send(conn);
954 return 0;
955 }
956 else if (ret == SSL_ERROR_WANT_READ) {
957 /* SSL handshake needs to read, L4 connection is ready */
958 if (conn->flags & CO_FL_WAIT_L4_CONN)
959 conn->flags &= ~CO_FL_WAIT_L4_CONN;
960 __conn_sock_stop_send(conn);
961 __conn_sock_poll_recv(conn);
962 return 0;
963 }
Willy Tarreau89230192012-09-28 20:22:13 +0200964 else if (ret == SSL_ERROR_SYSCALL) {
965 /* if errno is null, then connection was successfully established */
966 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
967 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +0100968
969 if (!((SSL *)conn->xprt_ctx)->packet_length)
970 if (!errno)
971 conn->err_code = CO_ER_SSL_EMPTY;
972 else
973 conn->err_code = CO_ER_SSL_ABORT;
974 else
975 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +0200976 goto out_error;
977 }
Emeric Brun46591952012-05-18 15:47:34 +0200978 else {
979 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +0200980 /* Note: OpenSSL may leave unread bytes in the socket's
981 * buffer, causing an RST to be emitted upon close() on
982 * TCP sockets. We first try to drain possibly pending
983 * data to avoid this as much as possible.
984 */
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100985 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Willy Tarreau20879a02012-12-03 16:32:10 +0100986 if (!conn->err_code)
987 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +0200988 goto out_error;
989 }
990 }
991
Emeric Brun674b7432012-11-08 19:21:55 +0100992reneg_ok:
993
Emeric Brun46591952012-05-18 15:47:34 +0200994 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100995 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200996 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +0200997 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100998 if (objt_server(conn->target)->ssl_ctx.reused_sess)
999 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001000
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001001 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001002 }
1003 }
1004
1005 /* The connection is now established at both layers, it's time to leave */
1006 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1007 return 1;
1008
1009 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001010 /* Clear openssl global errors stack */
1011 ERR_clear_error();
1012
Emeric Brun9fa89732012-10-04 17:09:56 +02001013 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001014 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1015 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1016 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001017 }
1018
Emeric Brun46591952012-05-18 15:47:34 +02001019 /* Fail on all other handshake errors */
1020 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001021 if (!conn->err_code)
1022 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001023 return 0;
1024}
1025
1026/* Receive up to <count> bytes from connection <conn>'s socket and store them
1027 * into buffer <buf>. The caller must ensure that <count> is always smaller
1028 * than the buffer's size. Only one call to recv() is performed, unless the
1029 * buffer wraps, in which case a second call may be performed. The connection's
1030 * flags are updated with whatever special event is detected (error, read0,
1031 * empty). The caller is responsible for taking care of those events and
1032 * avoiding the call if inappropriate. The function does not call the
1033 * connection's polling update function, so the caller is responsible for this.
1034 */
1035static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1036{
1037 int ret, done = 0;
1038 int try = count;
1039
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001040 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001041 goto out_error;
1042
1043 if (conn->flags & CO_FL_HANDSHAKE)
1044 /* a handshake was requested */
1045 return 0;
1046
1047 /* compute the maximum block size we can read at once. */
1048 if (buffer_empty(buf)) {
1049 /* let's realign the buffer to optimize I/O */
1050 buf->p = buf->data;
1051 }
1052 else if (buf->data + buf->o < buf->p &&
1053 buf->p + buf->i < buf->data + buf->size) {
1054 /* remaining space wraps at the end, with a moving limit */
1055 if (try > buf->data + buf->size - (buf->p + buf->i))
1056 try = buf->data + buf->size - (buf->p + buf->i);
1057 }
1058
1059 /* read the largest possible block. For this, we perform only one call
1060 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1061 * in which case we accept to do it once again. A new attempt is made on
1062 * EINTR too.
1063 */
1064 while (try) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001065 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001066 if (conn->flags & CO_FL_ERROR) {
1067 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001068 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001069 }
Emeric Brun46591952012-05-18 15:47:34 +02001070 if (ret > 0) {
1071 buf->i += ret;
1072 done += ret;
1073 if (ret < try)
1074 break;
1075 count -= ret;
1076 try = count;
1077 }
1078 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001079 ret = SSL_get_error(conn->xprt_ctx, ret);
1080 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001081 /* error on protocol or underlying transport */
1082 if ((ret != SSL_ERROR_SYSCALL)
1083 || (errno && (errno != EAGAIN)))
1084 conn->flags |= CO_FL_ERROR;
1085
Emeric Brun644cde02012-12-14 11:21:13 +01001086 /* Clear openssl global errors stack */
1087 ERR_clear_error();
1088 }
Emeric Brun46591952012-05-18 15:47:34 +02001089 goto read0;
1090 }
1091 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001092 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001093 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001094 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001095 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001096 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001097 break;
1098 }
1099 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001100 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1101 /* handshake is running, and it may need to re-enable read */
1102 conn->flags |= CO_FL_SSL_WAIT_HS;
1103 __conn_sock_want_recv(conn);
1104 break;
1105 }
Emeric Brun46591952012-05-18 15:47:34 +02001106 /* we need to poll for retry a read later */
1107 __conn_data_poll_recv(conn);
1108 break;
1109 }
1110 /* otherwise it's a real error */
1111 goto out_error;
1112 }
1113 }
1114 return done;
1115
1116 read0:
1117 conn_sock_read0(conn);
1118 return done;
1119 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001120 /* Clear openssl global errors stack */
1121 ERR_clear_error();
1122
Emeric Brun46591952012-05-18 15:47:34 +02001123 conn->flags |= CO_FL_ERROR;
1124 return done;
1125}
1126
1127
1128/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1129 * <flags> may contain MSG_MORE to make the system hold on without sending
1130 * data too fast, but this flag is ignored at the moment.
1131 * Only one call to send() is performed, unless the buffer wraps, in which case
1132 * a second call may be performed. The connection's flags are updated with
1133 * whatever special event is detected (error, empty). The caller is responsible
1134 * for taking care of those events and avoiding the call if inappropriate. The
1135 * function does not call the connection's polling update function, so the caller
1136 * is responsible for this.
1137 */
1138static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1139{
1140 int ret, try, done;
1141
1142 done = 0;
1143
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001144 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001145 goto out_error;
1146
1147 if (conn->flags & CO_FL_HANDSHAKE)
1148 /* a handshake was requested */
1149 return 0;
1150
1151 /* send the largest possible block. For this we perform only one call
1152 * to send() unless the buffer wraps and we exactly fill the first hunk,
1153 * in which case we accept to do it once again.
1154 */
1155 while (buf->o) {
1156 try = buf->o;
1157 /* outgoing data may wrap at the end */
1158 if (buf->data + try > buf->p)
1159 try = buf->data + try - buf->p;
1160
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001161 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001162 if (conn->flags & CO_FL_ERROR) {
1163 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001164 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001165 }
Emeric Brun46591952012-05-18 15:47:34 +02001166 if (ret > 0) {
1167 buf->o -= ret;
1168 done += ret;
1169
Willy Tarreau5fb38032012-12-16 19:39:09 +01001170 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001171 /* optimize data alignment in the buffer */
1172 buf->p = buf->data;
1173
1174 /* if the system buffer is full, don't insist */
1175 if (ret < try)
1176 break;
1177 }
1178 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001179 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001180 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001181 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1182 /* handshake is running, and it may need to re-enable write */
1183 conn->flags |= CO_FL_SSL_WAIT_HS;
1184 __conn_sock_want_send(conn);
1185 break;
1186 }
Emeric Brun46591952012-05-18 15:47:34 +02001187 /* we need to poll to retry a write later */
1188 __conn_data_poll_send(conn);
1189 break;
1190 }
1191 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001192 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001193 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001194 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001195 break;
1196 }
1197 goto out_error;
1198 }
1199 }
1200 return done;
1201
1202 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001203 /* Clear openssl global errors stack */
1204 ERR_clear_error();
1205
Emeric Brun46591952012-05-18 15:47:34 +02001206 conn->flags |= CO_FL_ERROR;
1207 return done;
1208}
1209
Emeric Brun46591952012-05-18 15:47:34 +02001210static void ssl_sock_close(struct connection *conn) {
1211
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001212 if (conn->xprt_ctx) {
1213 SSL_free(conn->xprt_ctx);
1214 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001215 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001216 }
Emeric Brun46591952012-05-18 15:47:34 +02001217}
1218
1219/* This function tries to perform a clean shutdown on an SSL connection, and in
1220 * any case, flags the connection as reusable if no handshake was in progress.
1221 */
1222static void ssl_sock_shutw(struct connection *conn, int clean)
1223{
1224 if (conn->flags & CO_FL_HANDSHAKE)
1225 return;
1226 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001227 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1228 /* Clear openssl global errors stack */
1229 ERR_clear_error();
1230 }
Emeric Brun46591952012-05-18 15:47:34 +02001231
1232 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001233 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001234}
1235
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001236/* used for logging, may be changed for a sample fetch later */
1237const char *ssl_sock_get_cipher_name(struct connection *conn)
1238{
1239 if (!conn->xprt && !conn->xprt_ctx)
1240 return NULL;
1241 return SSL_get_cipher_name(conn->xprt_ctx);
1242}
1243
1244/* used for logging, may be changed for a sample fetch later */
1245const char *ssl_sock_get_proto_version(struct connection *conn)
1246{
1247 if (!conn->xprt && !conn->xprt_ctx)
1248 return NULL;
1249 return SSL_get_version(conn->xprt_ctx);
1250}
1251
Willy Tarreau8d598402012-10-22 17:58:39 +02001252/* Extract a serial from a cert, and copy it to a chunk.
1253 * Returns 1 if serial is found and copied, 0 if no serial found and
1254 * -1 if output is not large enough.
1255 */
1256static int
1257ssl_sock_get_serial(X509 *crt, struct chunk *out)
1258{
1259 ASN1_INTEGER *serial;
1260
1261 serial = X509_get_serialNumber(crt);
1262 if (!serial)
1263 return 0;
1264
1265 if (out->size < serial->length)
1266 return -1;
1267
1268 memcpy(out->str, serial->data, serial->length);
1269 out->len = serial->length;
1270 return 1;
1271}
1272
Emeric Brunce5ad802012-10-22 14:11:22 +02001273
1274/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1275 * Returns 1 if serial is found and copied, 0 if no valid time found
1276 * and -1 if output is not large enough.
1277 */
1278static int
1279ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1280{
1281 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1282 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1283
1284 if (gentm->length < 12)
1285 return 0;
1286 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1287 return 0;
1288 if (out->size < gentm->length-2)
1289 return -1;
1290
1291 memcpy(out->str, gentm->data+2, gentm->length-2);
1292 out->len = gentm->length-2;
1293 return 1;
1294 }
1295 else if (tm->type == V_ASN1_UTCTIME) {
1296 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1297
1298 if (utctm->length < 10)
1299 return 0;
1300 if (utctm->data[0] >= 0x35)
1301 return 0;
1302 if (out->size < utctm->length)
1303 return -1;
1304
1305 memcpy(out->str, utctm->data, utctm->length);
1306 out->len = utctm->length;
1307 return 1;
1308 }
1309
1310 return 0;
1311}
1312
Emeric Brun87855892012-10-17 17:39:35 +02001313/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1314 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1315 */
1316static int
1317ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1318{
1319 X509_NAME_ENTRY *ne;
1320 int i, j, n;
1321 int cur = 0;
1322 const char *s;
1323 char tmp[128];
1324
1325 out->len = 0;
1326 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1327 if (pos < 0)
1328 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1329 else
1330 j = i;
1331
1332 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1333 n = OBJ_obj2nid(ne->object);
1334 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1335 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1336 s = tmp;
1337 }
1338
1339 if (chunk_strcasecmp(entry, s) != 0)
1340 continue;
1341
1342 if (pos < 0)
1343 cur--;
1344 else
1345 cur++;
1346
1347 if (cur != pos)
1348 continue;
1349
1350 if (ne->value->length > out->size)
1351 return -1;
1352
1353 memcpy(out->str, ne->value->data, ne->value->length);
1354 out->len = ne->value->length;
1355 return 1;
1356 }
1357
1358 return 0;
1359
1360}
1361
1362/* Extract and format full DN from a X509_NAME and copy result into a chunk
1363 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1364 */
1365static int
1366ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1367{
1368 X509_NAME_ENTRY *ne;
1369 int i, n, ln;
1370 int l = 0;
1371 const char *s;
1372 char *p;
1373 char tmp[128];
1374
1375 out->len = 0;
1376 p = out->str;
1377 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1378 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1379 n = OBJ_obj2nid(ne->object);
1380 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1381 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1382 s = tmp;
1383 }
1384 ln = strlen(s);
1385
1386 l += 1 + ln + 1 + ne->value->length;
1387 if (l > out->size)
1388 return -1;
1389 out->len = l;
1390
1391 *(p++)='/';
1392 memcpy(p, s, ln);
1393 p += ln;
1394 *(p++)='=';
1395 memcpy(p, ne->value->data, ne->value->length);
1396 p += ne->value->length;
1397 }
1398
1399 if (!out->len)
1400 return 0;
1401
1402 return 1;
1403}
1404
Willy Tarreau7875d092012-09-10 08:20:03 +02001405/***** Below are some sample fetching functions for ACL/patterns *****/
1406
Emeric Brune64aef12012-09-21 13:15:06 +02001407/* boolean, returns true if client cert was present */
1408static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001409smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1410 const struct arg *args, struct sample *smp)
Emeric Brune64aef12012-09-21 13:15:06 +02001411{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001412 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001413 return 0;
1414
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001415 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001416 smp->flags |= SMP_F_MAY_CHANGE;
1417 return 0;
1418 }
1419
1420 smp->flags = 0;
1421 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001422 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001423
1424 return 1;
1425}
1426
Willy Tarreau8d598402012-10-22 17:58:39 +02001427/* bin, returns serial in a binary chunk */
1428static int
1429smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1430 const struct arg *args, struct sample *smp)
1431{
1432 X509 *crt = NULL;
1433 int ret = 0;
1434 struct chunk *smp_trash;
1435
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001436 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001437 return 0;
1438
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001439 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001440 smp->flags |= SMP_F_MAY_CHANGE;
1441 return 0;
1442 }
1443
1444 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001445 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001446 if (!crt)
1447 goto out;
1448
Willy Tarreau47ca5452012-12-23 20:22:19 +01001449 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001450 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1451 goto out;
1452
1453 smp->data.str = *smp_trash;
1454 smp->type = SMP_T_BIN;
1455 ret = 1;
1456out:
1457 if (crt)
1458 X509_free(crt);
1459 return ret;
1460}
Emeric Brune64aef12012-09-21 13:15:06 +02001461
Emeric Brunce5ad802012-10-22 14:11:22 +02001462/*str, returns notafter date in ASN1_UTCTIME format */
1463static int
1464smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1465 const struct arg *args, struct sample *smp)
1466{
1467 X509 *crt = NULL;
1468 int ret = 0;
1469 struct chunk *smp_trash;
1470
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001471 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001472 return 0;
1473
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001474 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001475 smp->flags |= SMP_F_MAY_CHANGE;
1476 return 0;
1477 }
1478
1479 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001480 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001481 if (!crt)
1482 goto out;
1483
Willy Tarreau47ca5452012-12-23 20:22:19 +01001484 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001485 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1486 goto out;
1487
1488 smp->data.str = *smp_trash;
1489 smp->type = SMP_T_STR;
1490 ret = 1;
1491out:
1492 if (crt)
1493 X509_free(crt);
1494 return ret;
1495}
1496
Emeric Brun87855892012-10-17 17:39:35 +02001497/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1498static int
1499smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1500 const struct arg *args, struct sample *smp)
1501{
1502 X509 *crt = NULL;
1503 X509_NAME *name;
1504 int ret = 0;
1505 struct chunk *smp_trash;
1506
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001507 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001508 return 0;
1509
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001510 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001511 smp->flags |= SMP_F_MAY_CHANGE;
1512 return 0;
1513 }
1514
1515 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001516 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001517 if (!crt)
1518 goto out;
1519
1520 name = X509_get_issuer_name(crt);
1521 if (!name)
1522 goto out;
1523
Willy Tarreau47ca5452012-12-23 20:22:19 +01001524 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001525 if (args && args[0].type == ARGT_STR) {
1526 int pos = 1;
1527
1528 if (args[1].type == ARGT_SINT)
1529 pos = args[1].data.sint;
1530 else if (args[1].type == ARGT_UINT)
1531 pos =(int)args[1].data.uint;
1532
1533 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1534 goto out;
1535 }
1536 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1537 goto out;
1538
1539 smp->type = SMP_T_STR;
1540 smp->data.str = *smp_trash;
1541 ret = 1;
1542out:
1543 if (crt)
1544 X509_free(crt);
1545 return ret;
1546}
1547
Emeric Brunce5ad802012-10-22 14:11:22 +02001548/*str, returns notbefore date in ASN1_UTCTIME format */
1549static int
1550smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1551 const struct arg *args, struct sample *smp)
1552{
1553 X509 *crt = NULL;
1554 int ret = 0;
1555 struct chunk *smp_trash;
1556
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001557 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001558 return 0;
1559
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001560 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001561 smp->flags |= SMP_F_MAY_CHANGE;
1562 return 0;
1563 }
1564
1565 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001566 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001567 if (!crt)
1568 goto out;
1569
Willy Tarreau47ca5452012-12-23 20:22:19 +01001570 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001571 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1572 goto out;
1573
1574 smp->data.str = *smp_trash;
1575 smp->type = SMP_T_STR;
1576 ret = 1;
1577out:
1578 if (crt)
1579 X509_free(crt);
1580 return ret;
1581}
1582
Emeric Brun87855892012-10-17 17:39:35 +02001583/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1584static int
1585smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1586 const struct arg *args, struct sample *smp)
1587{
1588 X509 *crt = NULL;
1589 X509_NAME *name;
1590 int ret = 0;
1591 struct chunk *smp_trash;
1592
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001593 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001594 return 0;
1595
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001596 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001597 smp->flags |= SMP_F_MAY_CHANGE;
1598 return 0;
1599 }
1600
1601 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001602 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001603 if (!crt)
1604 goto out;
1605
1606 name = X509_get_subject_name(crt);
1607 if (!name)
1608 goto out;
1609
Willy Tarreau47ca5452012-12-23 20:22:19 +01001610 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001611 if (args && args[0].type == ARGT_STR) {
1612 int pos = 1;
1613
1614 if (args[1].type == ARGT_SINT)
1615 pos = args[1].data.sint;
1616 else if (args[1].type == ARGT_UINT)
1617 pos =(int)args[1].data.uint;
1618
1619 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1620 goto out;
1621 }
1622 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1623 goto out;
1624
1625 smp->type = SMP_T_STR;
1626 smp->data.str = *smp_trash;
1627 ret = 1;
1628out:
1629 if (crt)
1630 X509_free(crt);
1631 return ret;
1632}
Emeric Brun9143d372012-12-20 15:44:16 +01001633
1634/* integer, returns true if current session use a client certificate */
1635static int
1636smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1637 const struct arg *args, struct sample *smp)
1638{
1639 X509 *crt;
1640
1641 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
1642 return 0;
1643
1644 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
1645 smp->flags |= SMP_F_MAY_CHANGE;
1646 return 0;
1647 }
1648
1649 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
1650 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
1651 if (crt) {
1652 X509_free(crt);
1653 }
1654
1655 smp->type = SMP_T_BOOL;
1656 smp->data.uint = (crt != NULL);
1657 return 1;
1658}
1659
Emeric Bruna7359fd2012-10-17 15:03:11 +02001660/* integer, returns the client certificate version */
1661static int
1662smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1663 const struct arg *args, struct sample *smp)
1664{
1665 X509 *crt;
1666
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001667 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001668 return 0;
1669
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001670 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001671 smp->flags |= SMP_F_MAY_CHANGE;
1672 return 0;
1673 }
1674
1675 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001676 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001677 if (!crt)
1678 return 0;
1679
1680 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1681 X509_free(crt);
1682 smp->type = SMP_T_UINT;
1683
1684 return 1;
1685}
1686
Emeric Brun7f56e742012-10-19 18:15:40 +02001687/* str, returns the client certificate sig alg */
1688static int
1689smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1690 const struct arg *args, struct sample *smp)
1691{
1692 X509 *crt;
1693 int nid;
1694
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001695 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02001696 return 0;
1697
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001698 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02001699 smp->flags |= SMP_F_MAY_CHANGE;
1700 return 0;
1701 }
1702
1703 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001704 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02001705 if (!crt)
1706 return 0;
1707
1708 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1709
1710 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1711 if (!smp->data.str.str)
1712 return 0;
1713
1714 smp->type = SMP_T_CSTR;
1715 smp->data.str.len = strlen(smp->data.str.str);
1716 X509_free(crt);
1717
1718 return 1;
1719}
1720
Emeric Brun521a0112012-10-22 12:22:55 +02001721/* str, returns the client certificate key alg */
1722static int
1723smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1724 const struct arg *args, struct sample *smp)
1725{
1726 X509 *crt;
1727 int nid;
1728
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001729 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02001730 return 0;
1731
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001732 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02001733 smp->flags |= SMP_F_MAY_CHANGE;
1734 return 0;
1735 }
1736
1737 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001738 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02001739 if (!crt)
1740 return 0;
1741
1742 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1743
1744 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1745 if (!smp->data.str.str)
1746 return 0;
1747
1748 smp->type = SMP_T_CSTR;
1749 smp->data.str.len = strlen(smp->data.str.str);
1750 X509_free(crt);
1751
1752 return 1;
1753}
1754
Emeric Brun2525b6b2012-10-18 15:59:43 +02001755/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02001756static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001757smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau7875d092012-09-10 08:20:03 +02001758 const struct arg *args, struct sample *smp)
1759{
1760 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001761 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02001762 return 1;
1763}
1764
Emeric Brun2525b6b2012-10-18 15:59:43 +02001765/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02001766static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001767smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1768 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02001769{
1770#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1771 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001772 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock) &&
1773 l4->si[0].conn->xprt_ctx &&
1774 SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02001775 return 1;
1776#else
1777 return 0;
1778#endif
1779}
1780
Willy Tarreau8d598402012-10-22 17:58:39 +02001781/* bin, returns serial in a binary chunk */
1782static int
1783smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1784 const struct arg *args, struct sample *smp)
1785{
1786 X509 *crt = NULL;
1787 int ret = 0;
1788 struct chunk *smp_trash;
1789
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001790 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001791 return 0;
1792
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001793 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001794 smp->flags |= SMP_F_MAY_CHANGE;
1795 return 0;
1796 }
1797
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001798 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001799 if (!crt)
1800 goto out;
1801
Willy Tarreau47ca5452012-12-23 20:22:19 +01001802 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001803 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1804 goto out;
1805
1806 smp->data.str = *smp_trash;
1807 smp->type = SMP_T_BIN;
1808 ret = 1;
1809out:
1810 return ret;
1811}
Emeric Brunce5ad802012-10-22 14:11:22 +02001812/*str, returns notafter date in ASN1_UTCTIME format */
1813static int
1814smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1815 const struct arg *args, struct sample *smp)
1816{
1817 X509 *crt = NULL;
1818 int ret = 0;
1819 struct chunk *smp_trash;
1820
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001821 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001822 return 0;
1823
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001824 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001825 smp->flags |= SMP_F_MAY_CHANGE;
1826 return 0;
1827 }
1828
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001829 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001830 if (!crt)
1831 goto out;
1832
Willy Tarreau47ca5452012-12-23 20:22:19 +01001833 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001834 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1835 goto out;
1836
1837 smp->data.str = *smp_trash;
1838 smp->type = SMP_T_STR;
1839 ret = 1;
1840out:
1841 return ret;
1842}
1843
1844/*str, returns notbefore date in ASN1_UTCTIME format */
1845static int
1846smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1847 const struct arg *args, struct sample *smp)
1848{
1849 X509 *crt = NULL;
1850 int ret = 0;
1851 struct chunk *smp_trash;
1852
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001853 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001854 return 0;
1855
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001856 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001857 smp->flags |= SMP_F_MAY_CHANGE;
1858 return 0;
1859 }
1860
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001861 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001862 if (!crt)
1863 goto out;
1864
Willy Tarreau47ca5452012-12-23 20:22:19 +01001865 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001866 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1867 goto out;
1868
1869 smp->data.str = *smp_trash;
1870 smp->type = SMP_T_STR;
1871 ret = 1;
1872out:
1873 return ret;
1874}
Willy Tarreau8d598402012-10-22 17:58:39 +02001875
Emeric Bruna7359fd2012-10-17 15:03:11 +02001876/* integer, returns the frontend certificate version */
1877static int
1878smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1879 const struct arg *args, struct sample *smp)
1880{
1881 X509 *crt;
1882
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001883 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001884 return 0;
1885
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001886 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001887 smp->flags |= SMP_F_MAY_CHANGE;
1888 return 0;
1889 }
1890
1891 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001892 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001893 if (!crt)
1894 return 0;
1895
1896 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1897 smp->type = SMP_T_UINT;
1898
1899 return 1;
1900}
1901
Emeric Brun7f56e742012-10-19 18:15:40 +02001902/* str, returns the client certificate sig alg */
1903static int
1904smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1905 const struct arg *args, struct sample *smp)
1906{
1907 X509 *crt;
1908 int nid;
1909
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001910 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02001911 return 0;
1912
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001913 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02001914 smp->flags |= SMP_F_MAY_CHANGE;
1915 return 0;
1916 }
1917
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001918 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02001919 if (!crt)
1920 return 0;
1921
1922 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1923
1924 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1925 if (!smp->data.str.str)
1926 return 0;
1927
1928 smp->type = SMP_T_CSTR;
1929 smp->data.str.len = strlen(smp->data.str.str);
1930
1931 return 1;
1932}
1933
Emeric Brun521a0112012-10-22 12:22:55 +02001934/* str, returns the client certificate key alg */
1935static int
1936smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1937 const struct arg *args, struct sample *smp)
1938{
1939 X509 *crt;
1940 int nid;
1941
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001942 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02001943 return 0;
1944
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001945 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02001946 smp->flags |= SMP_F_MAY_CHANGE;
1947 return 0;
1948 }
1949
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001950 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02001951 if (!crt)
1952 return 0;
1953
1954 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1955
1956 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1957 if (!smp->data.str.str)
1958 return 0;
1959
1960 smp->type = SMP_T_CSTR;
1961 smp->data.str.len = strlen(smp->data.str.str);
1962
1963 return 1;
1964}
1965
Emeric Brun87855892012-10-17 17:39:35 +02001966/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1967static int
1968smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1969 const struct arg *args, struct sample *smp)
1970{
1971 X509 *crt = NULL;
1972 X509_NAME *name;
1973 int ret = 0;
1974 struct chunk *smp_trash;
1975
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001976 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001977 return 0;
1978
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001979 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001980 smp->flags |= SMP_F_MAY_CHANGE;
1981 return 0;
1982 }
1983
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001984 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001985 if (!crt)
1986 goto out;
1987
1988 name = X509_get_issuer_name(crt);
1989 if (!name)
1990 goto out;
1991
Willy Tarreau47ca5452012-12-23 20:22:19 +01001992 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001993 if (args && args[0].type == ARGT_STR) {
1994 int pos = 1;
1995
1996 if (args[1].type == ARGT_SINT)
1997 pos = args[1].data.sint;
1998 else if (args[1].type == ARGT_UINT)
1999 pos =(int)args[1].data.uint;
2000
2001 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2002 goto out;
2003 }
2004 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2005 goto out;
2006
2007 smp->type = SMP_T_STR;
2008 smp->data.str = *smp_trash;
2009 ret = 1;
2010out:
2011 return ret;
2012}
2013
2014/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2015static int
2016smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2017 const struct arg *args, struct sample *smp)
2018{
2019 X509 *crt = NULL;
2020 X509_NAME *name;
2021 int ret = 0;
2022 struct chunk *smp_trash;
2023
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002024 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002025 return 0;
2026
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002027 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002028 smp->flags |= SMP_F_MAY_CHANGE;
2029 return 0;
2030 }
2031
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002032 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002033 if (!crt)
2034 goto out;
2035
2036 name = X509_get_subject_name(crt);
2037 if (!name)
2038 goto out;
2039
Willy Tarreau47ca5452012-12-23 20:22:19 +01002040 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002041 if (args && args[0].type == ARGT_STR) {
2042 int pos = 1;
2043
2044 if (args[1].type == ARGT_SINT)
2045 pos = args[1].data.sint;
2046 else if (args[1].type == ARGT_UINT)
2047 pos =(int)args[1].data.uint;
2048
2049 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2050 goto out;
2051 }
2052 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2053 goto out;
2054
2055 smp->type = SMP_T_STR;
2056 smp->data.str = *smp_trash;
2057 ret = 1;
2058out:
2059 return ret;
2060}
2061
Emeric Brun589fcad2012-10-16 14:13:26 +02002062static int
2063smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2064 const struct arg *args, struct sample *smp)
2065{
2066 smp->flags = 0;
2067
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002068 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002069 return 0;
2070
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002071 smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002072 if (!smp->data.str.str)
2073 return 0;
2074
2075 smp->type = SMP_T_CSTR;
2076 smp->data.str.len = strlen(smp->data.str.str);
2077
2078 return 1;
2079}
2080
2081static int
2082smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2083 const struct arg *args, struct sample *smp)
2084{
2085 smp->flags = 0;
2086
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002087 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002088 return 0;
2089
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002090 if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
Emeric Brun589fcad2012-10-16 14:13:26 +02002091 return 0;
2092
2093 smp->type = SMP_T_UINT;
2094
2095 return 1;
2096}
2097
2098static int
2099smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2100 const struct arg *args, struct sample *smp)
2101{
2102 smp->flags = 0;
2103
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002104 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002105 return 0;
2106
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002107 smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002108 if (!smp->data.uint)
2109 return 0;
2110
2111 smp->type = SMP_T_UINT;
2112
2113 return 1;
2114}
2115
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002116#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002117static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002118smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2119 const struct arg *args, struct sample *smp)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002120{
Willy Tarreaua33c6542012-10-15 13:19:06 +02002121 smp->flags = 0;
2122 smp->type = SMP_T_CSTR;
2123
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002124 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002125 return 0;
2126
2127 smp->data.str.str = NULL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002128 SSL_get0_next_proto_negotiated(l4->si[0].conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002129 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2130
2131 if (!smp->data.str.str)
2132 return 0;
2133
2134 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002135}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002136#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002137
2138static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002139smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2140 const struct arg *args, struct sample *smp)
2141{
2142 smp->flags = 0;
2143
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002144 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002145 return 0;
2146
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002147 smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002148 if (!smp->data.str.str)
2149 return 0;
2150
2151 smp->type = SMP_T_CSTR;
2152 smp->data.str.len = strlen(smp->data.str.str);
2153
2154 return 1;
2155}
2156
2157static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002158smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2159 const struct arg *args, struct sample *smp)
2160{
2161#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2162 SSL_SESSION *sess;
2163
2164 smp->flags = 0;
2165 smp->type = SMP_T_CBIN;
2166
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002167 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunfe68f682012-10-16 14:59:28 +02002168 return 0;
2169
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002170 sess = SSL_get_session(l4->si[0].conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002171 if (!sess)
2172 return 0;
2173
2174 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2175 if (!smp->data.str.str || !&smp->data.str.len)
2176 return 0;
2177
2178 return 1;
2179#else
2180 return 0;
2181#endif
2182}
2183
2184static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002185smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2186 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02002187{
2188#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2189 smp->flags = 0;
2190 smp->type = SMP_T_CSTR;
2191
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002192 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau7875d092012-09-10 08:20:03 +02002193 return 0;
2194
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002195 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 +02002196 if (!smp->data.str.str)
2197 return 0;
2198
Willy Tarreau7875d092012-09-10 08:20:03 +02002199 smp->data.str.len = strlen(smp->data.str.str);
2200 return 1;
2201#else
2202 return 0;
2203#endif
2204}
2205
Emeric Brun2525b6b2012-10-18 15:59:43 +02002206/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002207static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002208smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002209 const struct arg *args, struct sample *smp)
2210{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002211 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002212 return 0;
2213
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002214 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002215 smp->flags = SMP_F_MAY_CHANGE;
2216 return 0;
2217 }
2218
2219 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002220 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002221 smp->flags = 0;
2222
2223 return 1;
2224}
2225
Emeric Brun2525b6b2012-10-18 15:59:43 +02002226/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002227static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002228smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002229 const struct arg *args, struct sample *smp)
2230{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002231 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002232 return 0;
2233
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002234 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002235 smp->flags = SMP_F_MAY_CHANGE;
2236 return 0;
2237 }
2238
2239 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002240 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002241 smp->flags = 0;
2242
2243 return 1;
2244}
2245
Emeric Brun2525b6b2012-10-18 15:59:43 +02002246/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002247static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002248smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2249 const struct arg *args, struct sample *smp)
Emeric Brunf282a812012-09-21 15:27:54 +02002250{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002251 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002252 return 0;
2253
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002254 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002255 smp->flags = SMP_F_MAY_CHANGE;
2256 return 0;
2257 }
2258
2259 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002260 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002261 smp->flags = 0;
2262
2263 return 1;
2264}
2265
Emeric Brun2525b6b2012-10-18 15:59:43 +02002266/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002267static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002268smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2269 const struct arg *args, struct sample *smp)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002270{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002271 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002272 return 0;
2273
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002274 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002275 smp->flags = SMP_F_MAY_CHANGE;
2276 return 0;
2277 }
2278
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002279 if (!l4->si[0].conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002280 return 0;
2281
2282 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002283 smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002284 smp->flags = 0;
2285
2286 return 1;
2287}
2288
Emeric Brunfb510ea2012-10-05 12:00:26 +02002289/* parse the "ca-file" bind keyword */
2290static 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 +02002291{
2292 if (!*args[cur_arg + 1]) {
2293 if (err)
2294 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2295 return ERR_ALERT | ERR_FATAL;
2296 }
2297
Emeric Brunef42d922012-10-11 16:11:36 +02002298 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2299 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2300 else
2301 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002302
Emeric Brund94b3fe2012-09-20 18:23:56 +02002303 return 0;
2304}
2305
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002306/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002307static 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 +02002308{
2309 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002310 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002311 return ERR_ALERT | ERR_FATAL;
2312 }
2313
Emeric Brun76d88952012-10-05 15:47:31 +02002314 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002315 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002316 return 0;
2317}
2318
2319/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002320static 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 +02002321{
Emeric Brunc8e8d122012-10-02 18:42:10 +02002322 char path[PATH_MAX];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002323 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002324 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002325 return ERR_ALERT | ERR_FATAL;
2326 }
2327
Emeric Brunc8e8d122012-10-02 18:42:10 +02002328 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
2329 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > PATH_MAX) {
2330 memprintf(err, "'%s' : path too long", args[cur_arg]);
2331 return ERR_ALERT | ERR_FATAL;
2332 }
2333 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2334 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2335 return ERR_ALERT | ERR_FATAL;
2336
2337 return 0;
2338 }
2339
Willy Tarreau4348fad2012-09-20 16:48:07 +02002340 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002341 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002342
2343 return 0;
2344}
2345
Emeric Brunfb510ea2012-10-05 12:00:26 +02002346/* parse the "crl-file" bind keyword */
2347static 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 +02002348{
Emeric Brun051cdab2012-10-02 19:25:50 +02002349#ifndef X509_V_FLAG_CRL_CHECK
2350 if (err)
2351 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2352 return ERR_ALERT | ERR_FATAL;
2353#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002354 if (!*args[cur_arg + 1]) {
2355 if (err)
2356 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2357 return ERR_ALERT | ERR_FATAL;
2358 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002359
Emeric Brunef42d922012-10-11 16:11:36 +02002360 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2361 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2362 else
2363 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002364
Emeric Brun2b58d042012-09-20 17:10:03 +02002365 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002366#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002367}
2368
2369/* parse the "ecdhe" bind keyword keywords */
2370static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2371{
2372#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2373 if (err)
2374 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2375 return ERR_ALERT | ERR_FATAL;
2376#elif defined(OPENSSL_NO_ECDH)
2377 if (err)
2378 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2379 return ERR_ALERT | ERR_FATAL;
2380#else
2381 if (!*args[cur_arg + 1]) {
2382 if (err)
2383 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2384 return ERR_ALERT | ERR_FATAL;
2385 }
2386
2387 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002388
2389 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002390#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002391}
2392
Emeric Brun81c00f02012-09-21 14:31:21 +02002393/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2394static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2395{
2396 int code;
2397 char *p = args[cur_arg + 1];
2398 unsigned long long *ignerr = &conf->crt_ignerr;
2399
2400 if (!*p) {
2401 if (err)
2402 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2403 return ERR_ALERT | ERR_FATAL;
2404 }
2405
2406 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2407 ignerr = &conf->ca_ignerr;
2408
2409 if (strcmp(p, "all") == 0) {
2410 *ignerr = ~0ULL;
2411 return 0;
2412 }
2413
2414 while (p) {
2415 code = atoi(p);
2416 if ((code <= 0) || (code > 63)) {
2417 if (err)
2418 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2419 args[cur_arg], code, args[cur_arg + 1]);
2420 return ERR_ALERT | ERR_FATAL;
2421 }
2422 *ignerr |= 1ULL << code;
2423 p = strchr(p, ',');
2424 if (p)
2425 p++;
2426 }
2427
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002428 return 0;
2429}
2430
2431/* parse the "force-sslv3" bind keyword */
2432static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2433{
2434 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2435 return 0;
2436}
2437
2438/* parse the "force-tlsv10" bind keyword */
2439static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2440{
2441 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002442 return 0;
2443}
2444
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002445/* parse the "force-tlsv11" bind keyword */
2446static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2447{
2448#if SSL_OP_NO_TLSv1_1
2449 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
2450 return 0;
2451#else
2452 if (err)
2453 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
2454 return ERR_ALERT | ERR_FATAL;
2455#endif
2456}
2457
2458/* parse the "force-tlsv12" bind keyword */
2459static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2460{
2461#if SSL_OP_NO_TLSv1_2
2462 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
2463 return 0;
2464#else
2465 if (err)
2466 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
2467 return ERR_ALERT | ERR_FATAL;
2468#endif
2469}
2470
2471
Emeric Brun2d0c4822012-10-02 13:45:20 +02002472/* parse the "no-tls-tickets" bind keyword */
2473static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2474{
Emeric Brun89675492012-10-05 13:48:26 +02002475 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02002476 return 0;
2477}
2478
Emeric Brun2d0c4822012-10-02 13:45:20 +02002479
Emeric Brun9b3009b2012-10-05 11:55:06 +02002480/* parse the "no-sslv3" bind keyword */
2481static 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 +02002482{
Emeric Brun89675492012-10-05 13:48:26 +02002483 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002484 return 0;
2485}
2486
Emeric Brun9b3009b2012-10-05 11:55:06 +02002487/* parse the "no-tlsv10" bind keyword */
2488static 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 +02002489{
Emeric Brun89675492012-10-05 13:48:26 +02002490 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002491 return 0;
2492}
2493
Emeric Brun9b3009b2012-10-05 11:55:06 +02002494/* parse the "no-tlsv11" bind keyword */
2495static 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 +02002496{
Emeric Brun89675492012-10-05 13:48:26 +02002497 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002498 return 0;
2499}
2500
Emeric Brun9b3009b2012-10-05 11:55:06 +02002501/* parse the "no-tlsv12" bind keyword */
2502static 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 +02002503{
Emeric Brun89675492012-10-05 13:48:26 +02002504 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002505 return 0;
2506}
2507
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002508/* parse the "npn" bind keyword */
2509static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2510{
2511#ifdef OPENSSL_NPN_NEGOTIATED
2512 char *p1, *p2;
2513
2514 if (!*args[cur_arg + 1]) {
2515 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
2516 return ERR_ALERT | ERR_FATAL;
2517 }
2518
2519 free(conf->npn_str);
2520
2521 /* the NPN string is built as a suite of (<len> <name>)* */
2522 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
2523 conf->npn_str = calloc(1, conf->npn_len);
2524 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
2525
2526 /* replace commas with the name length */
2527 p1 = conf->npn_str;
2528 p2 = p1 + 1;
2529 while (1) {
2530 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
2531 if (!p2)
2532 p2 = p1 + 1 + strlen(p1 + 1);
2533
2534 if (p2 - (p1 + 1) > 255) {
2535 *p2 = '\0';
2536 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2537 return ERR_ALERT | ERR_FATAL;
2538 }
2539
2540 *p1 = p2 - (p1 + 1);
2541 p1 = p2;
2542
2543 if (!*p2)
2544 break;
2545
2546 *(p2++) = '\0';
2547 }
2548 return 0;
2549#else
2550 if (err)
2551 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
2552 return ERR_ALERT | ERR_FATAL;
2553#endif
2554}
2555
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002556/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002557static 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 +02002558{
Willy Tarreau81796be2012-09-22 19:11:47 +02002559 struct listener *l;
2560
Willy Tarreau4348fad2012-09-20 16:48:07 +02002561 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02002562
2563 if (global.listen_default_ciphers && !conf->ciphers)
2564 conf->ciphers = strdup(global.listen_default_ciphers);
2565
Willy Tarreau81796be2012-09-22 19:11:47 +02002566 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002567 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02002568
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002569 return 0;
2570}
2571
Emeric Brund94b3fe2012-09-20 18:23:56 +02002572/* parse the "verify" bind keyword */
2573static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2574{
2575 if (!*args[cur_arg + 1]) {
2576 if (err)
2577 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
2578 return ERR_ALERT | ERR_FATAL;
2579 }
2580
2581 if (strcmp(args[cur_arg + 1], "none") == 0)
2582 conf->verify = SSL_VERIFY_NONE;
2583 else if (strcmp(args[cur_arg + 1], "optional") == 0)
2584 conf->verify = SSL_VERIFY_PEER;
2585 else if (strcmp(args[cur_arg + 1], "required") == 0)
2586 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2587 else {
2588 if (err)
2589 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
2590 args[cur_arg], args[cur_arg + 1]);
2591 return ERR_ALERT | ERR_FATAL;
2592 }
2593
2594 return 0;
2595}
2596
Willy Tarreau92faadf2012-10-10 23:04:25 +02002597/************** "server" keywords ****************/
2598
Emeric Brunef42d922012-10-11 16:11:36 +02002599/* parse the "ca-file" server keyword */
2600static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2601{
2602 if (!*args[*cur_arg + 1]) {
2603 if (err)
2604 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
2605 return ERR_ALERT | ERR_FATAL;
2606 }
2607
2608 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2609 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2610 else
2611 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
2612
2613 return 0;
2614}
2615
Willy Tarreau92faadf2012-10-10 23:04:25 +02002616/* parse the "check-ssl" server keyword */
2617static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2618{
2619 newsrv->check.use_ssl = 1;
2620 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2621 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2622 return 0;
2623}
2624
2625/* parse the "ciphers" server keyword */
2626static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2627{
2628 if (!*args[*cur_arg + 1]) {
2629 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
2630 return ERR_ALERT | ERR_FATAL;
2631 }
2632
2633 free(newsrv->ssl_ctx.ciphers);
2634 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
2635 return 0;
2636}
2637
Emeric Brunef42d922012-10-11 16:11:36 +02002638/* parse the "crl-file" server keyword */
2639static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2640{
2641#ifndef X509_V_FLAG_CRL_CHECK
2642 if (err)
2643 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
2644 return ERR_ALERT | ERR_FATAL;
2645#else
2646 if (!*args[*cur_arg + 1]) {
2647 if (err)
2648 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
2649 return ERR_ALERT | ERR_FATAL;
2650 }
2651
2652 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2653 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2654 else
2655 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
2656
2657 return 0;
2658#endif
2659}
2660
Emeric Bruna7aa3092012-10-26 12:58:00 +02002661/* parse the "crt" server keyword */
2662static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2663{
2664 if (!*args[*cur_arg + 1]) {
2665 if (err)
2666 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
2667 return ERR_ALERT | ERR_FATAL;
2668 }
2669
2670 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
2671 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2672 else
2673 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
2674
2675 return 0;
2676}
Emeric Brunef42d922012-10-11 16:11:36 +02002677
Willy Tarreau92faadf2012-10-10 23:04:25 +02002678/* parse the "force-sslv3" server keyword */
2679static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2680{
2681 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
2682 return 0;
2683}
2684
2685/* parse the "force-tlsv10" server keyword */
2686static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2687{
2688 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
2689 return 0;
2690}
2691
2692/* parse the "force-tlsv11" server keyword */
2693static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2694{
2695#if SSL_OP_NO_TLSv1_1
2696 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
2697 return 0;
2698#else
2699 if (err)
2700 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
2701 return ERR_ALERT | ERR_FATAL;
2702#endif
2703}
2704
2705/* parse the "force-tlsv12" server keyword */
2706static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2707{
2708#if SSL_OP_NO_TLSv1_2
2709 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
2710 return 0;
2711#else
2712 if (err)
2713 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
2714 return ERR_ALERT | ERR_FATAL;
2715#endif
2716}
2717
2718/* parse the "no-sslv3" server keyword */
2719static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2720{
2721 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
2722 return 0;
2723}
2724
2725/* parse the "no-tlsv10" server keyword */
2726static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2727{
2728 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
2729 return 0;
2730}
2731
2732/* parse the "no-tlsv11" server keyword */
2733static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2734{
2735 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
2736 return 0;
2737}
2738
2739/* parse the "no-tlsv12" server keyword */
2740static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2741{
2742 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
2743 return 0;
2744}
2745
Emeric Brunf9c5c472012-10-11 15:28:34 +02002746/* parse the "no-tls-tickets" server keyword */
2747static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2748{
2749 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
2750 return 0;
2751}
2752
Willy Tarreau92faadf2012-10-10 23:04:25 +02002753/* parse the "ssl" server keyword */
2754static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2755{
2756 newsrv->use_ssl = 1;
2757 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2758 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2759 return 0;
2760}
2761
Emeric Brunef42d922012-10-11 16:11:36 +02002762/* parse the "verify" server keyword */
2763static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2764{
2765 if (!*args[*cur_arg + 1]) {
2766 if (err)
2767 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
2768 return ERR_ALERT | ERR_FATAL;
2769 }
2770
2771 if (strcmp(args[*cur_arg + 1], "none") == 0)
2772 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
2773 else if (strcmp(args[*cur_arg + 1], "required") == 0)
2774 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
2775 else {
2776 if (err)
2777 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
2778 args[*cur_arg], args[*cur_arg + 1]);
2779 return ERR_ALERT | ERR_FATAL;
2780 }
2781
2782 return 0;
2783}
2784
Willy Tarreau7875d092012-09-10 08:20:03 +02002785/* Note: must not be declared <const> as its list will be overwritten.
2786 * Please take care of keeping this list alphabetically sorted.
2787 */
2788static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
Emeric Brun2525b6b2012-10-18 15:59:43 +02002789 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2790 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2791 { "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 +02002792 { "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 +02002793 { "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 +02002794 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
2795 { "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 +02002796 { "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 +02002797 { "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 +02002798 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun9143d372012-12-20 15:44:16 +01002799 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002800 { "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 +02002801 { "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 +02002802 { "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 +02002803 { "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 +02002804 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
2805 { "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 +02002806 { "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 +02002807 { "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 +02002808 { "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 +02002809 { "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 +02002810 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun589fcad2012-10-16 14:13:26 +02002811 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2812 { "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 +02002813 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
2814 { "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 +02002815#ifdef OPENSSL_NPN_NEGOTIATED
Emeric Brun2525b6b2012-10-18 15:59:43 +02002816 { "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 +02002817#endif
Emeric Brun589fcad2012-10-16 14:13:26 +02002818 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
2819 { "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 +02002820 { "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 +02002821 { "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 +02002822 { NULL, NULL, 0, 0, 0 },
2823}};
2824
2825/* Note: must not be declared <const> as its list will be overwritten.
2826 * Please take care of keeping this list alphabetically sorted.
2827 */
2828static struct acl_kw_list acl_kws = {{ },{
Emeric Brun2525b6b2012-10-18 15:59:43 +02002829 { "ssl_c_ca_err", acl_parse_int, smp_fetch_ssl_c_ca_err, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2830 { "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 },
2831 { "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 +02002832 { "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 +02002833 { "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 +02002834 { "ssl_c_notafter", acl_parse_str, smp_fetch_ssl_c_notafter, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2835 { "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 +02002836 { "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 +02002837 { "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 +02002838 { "ssl_c_serial", acl_parse_bin, smp_fetch_ssl_c_serial, acl_match_bin, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun9143d372012-12-20 15:44:16 +01002839 { "ssl_c_used", acl_parse_int, smp_fetch_ssl_c_used, acl_match_nothing, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002840 { "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 +02002841 { "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 +02002842 { "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 +02002843 { "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 +02002844 { "ssl_f_notafter", acl_parse_str, smp_fetch_ssl_f_notafter, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2845 { "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 +02002846 { "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 +02002847 { "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 +02002848 { "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 +02002849 { "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 +02002850 { "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 +02002851 { "ssl_fc_alg_keysize", acl_parse_str, smp_fetch_ssl_fc_alg_keysize, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2852 { "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 +02002853 { "ssl_fc_has_crt", acl_parse_int, smp_fetch_ssl_fc_has_crt, acl_match_nothing, ACL_USE_L6REQ_PERMANENT, 0 },
2854 { "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 +02002855#ifdef OPENSSL_NPN_NEGOTIATED
Emeric Brun2525b6b2012-10-18 15:59:43 +02002856 { "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 +02002857#endif
Emeric Brun589fcad2012-10-16 14:13:26 +02002858 { "ssl_fc_protocol", acl_parse_str, smp_fetch_ssl_fc_protocol, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2859 { "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 +02002860 { "ssl_fc_sni", acl_parse_str, smp_fetch_ssl_fc_sni, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2861 { "ssl_fc_sni_end", acl_parse_str, smp_fetch_ssl_fc_sni, acl_match_end, ACL_USE_L6REQ_PERMANENT, 0 },
2862 { "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 +02002863 { NULL, NULL, NULL, NULL },
2864}};
2865
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002866/* Note: must not be declared <const> as its list will be overwritten.
2867 * Please take care of keeping this list alphabetically sorted, doing so helps
2868 * all code contributors.
2869 * Optional keywords are also declared with a NULL ->parse() function so that
2870 * the config parser can report an appropriate error when a known keyword was
2871 * not enabled.
2872 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02002873static struct bind_kw_list bind_kws = { "SSL", { }, {
Emeric Brunfb510ea2012-10-05 12:00:26 +02002874 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002875 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
2876 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02002877 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002878 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
2879 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
2880 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002881 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
2882 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
2883 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
2884 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02002885 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
2886 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
2887 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
2888 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002889 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002890 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
2891 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002892 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002893 { NULL, NULL, 0 },
2894}};
Emeric Brun46591952012-05-18 15:47:34 +02002895
Willy Tarreau92faadf2012-10-10 23:04:25 +02002896/* Note: must not be declared <const> as its list will be overwritten.
2897 * Please take care of keeping this list alphabetically sorted, doing so helps
2898 * all code contributors.
2899 * Optional keywords are also declared with a NULL ->parse() function so that
2900 * the config parser can report an appropriate error when a known keyword was
2901 * not enabled.
2902 */
2903static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02002904 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002905 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
2906 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02002907 { "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 +02002908 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002909 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
2910 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
2911 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
2912 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
2913 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
2914 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
2915 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
2916 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02002917 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002918 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02002919 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Willy Tarreau92faadf2012-10-10 23:04:25 +02002920 { NULL, NULL, 0, 0 },
2921}};
2922
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002923/* transport-layer operations for SSL sockets */
2924struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02002925 .snd_buf = ssl_sock_from_buf,
2926 .rcv_buf = ssl_sock_to_buf,
2927 .rcv_pipe = NULL,
2928 .snd_pipe = NULL,
2929 .shutr = NULL,
2930 .shutw = ssl_sock_shutw,
2931 .close = ssl_sock_close,
2932 .init = ssl_sock_init,
2933};
2934
2935__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02002936static void __ssl_sock_init(void)
2937{
Emeric Brun46591952012-05-18 15:47:34 +02002938 STACK_OF(SSL_COMP)* cm;
2939
2940 SSL_library_init();
2941 cm = SSL_COMP_get_compression_methods();
2942 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02002943 sample_register_fetches(&sample_fetch_keywords);
2944 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002945 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02002946 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02002947}
2948
2949/*
2950 * Local variables:
2951 * c-indent-level: 8
2952 * c-basic-offset: 8
2953 * End:
2954 */