blob: 73d97c2540e357a768c12d083ddc0c74234e0dc2 [file] [log] [blame]
Emeric Brun46591952012-05-18 15:47:34 +02001/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02003 *
4 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
Willy Tarreau69845df2012-09-10 09:43:09 +020011 * Acknowledgement:
12 * We'd like to specially thank the Stud project authors for a very clean
13 * and well documented code which helped us understand how the OpenSSL API
14 * ought to be used in non-blocking mode. This is one difficult part which
15 * is not easy to get from the OpenSSL doc, and reading the Stud code made
16 * it much more obvious than the examples in the OpenSSL package. Keep up
17 * the good works, guys !
18 *
19 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
20 * particularly well with haproxy. For more info about this project, visit :
21 * https://github.com/bumptech/stud
22 *
Emeric Brun46591952012-05-18 15:47:34 +020023 */
24
25#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020026#include <ctype.h>
27#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020028#include <errno.h>
29#include <fcntl.h>
30#include <stdio.h>
31#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020032#include <string.h>
33#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020034
35#include <sys/socket.h>
36#include <sys/stat.h>
37#include <sys/types.h>
38
39#include <netinet/tcp.h>
40
41#include <openssl/ssl.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020042#include <openssl/x509.h>
43#include <openssl/x509v3.h>
44#include <openssl/x509.h>
45#include <openssl/err.h>
Emeric Brun46591952012-05-18 15:47:34 +020046
47#include <common/buffer.h>
48#include <common/compat.h>
49#include <common/config.h>
50#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020051#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020052#include <common/standard.h>
53#include <common/ticks.h>
54#include <common/time.h>
55
Emeric Brunfc0421f2012-09-07 17:30:07 +020056#include <ebsttree.h>
57
58#include <types/global.h>
59#include <types/ssl_sock.h>
60
Willy Tarreau7875d092012-09-10 08:20:03 +020061#include <proto/acl.h>
62#include <proto/arg.h>
Emeric Brun46591952012-05-18 15:47:34 +020063#include <proto/connection.h>
64#include <proto/fd.h>
65#include <proto/freq_ctr.h>
66#include <proto/frontend.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020067#include <proto/listener.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020068#include <proto/server.h>
Emeric Brun46591952012-05-18 15:47:34 +020069#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +020070#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +020072#include <proto/ssl_sock.h>
73#include <proto/task.h>
74
Emeric Brune64aef12012-09-21 13:15:06 +020075#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brunf282a812012-09-21 15:27:54 +020076/* bits 0xFFFF0000 are reserved to store verify errors */
77
78/* Verify errors macros */
79#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
80#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
81#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
82
83#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
84#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
85#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +020086
Willy Tarreau403edff2012-09-06 11:58:37 +020087static int sslconns = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +020088
89void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
90{
91 struct connection *conn = (struct connection *)SSL_get_app_data(ssl);
92 (void)ret; /* shut gcc stupid warning */
93
94 if (where & SSL_CB_HANDSHAKE_START) {
95 /* Disable renegotiation (CVE-2009-3555) */
96 if (conn->flags & CO_FL_CONNECTED)
97 conn->flags |= CO_FL_ERROR;
98 }
Emeric Brunfc0421f2012-09-07 17:30:07 +020099}
100
Emeric Brune64aef12012-09-21 13:15:06 +0200101/* Callback is called for each certificate of the chain during a verify
102 ok is set to 1 if preverify detect no error on current certificate.
103 Returns 0 to break the handshake, 1 otherwise. */
104int ssl_sock_verifycbk(int ok, X509_STORE_CTX *x_store)
105{
106 SSL *ssl;
107 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +0200108 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +0200109
110 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
111 conn = (struct connection *)SSL_get_app_data(ssl);
112
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200113 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +0200114
Emeric Brun81c00f02012-09-21 14:31:21 +0200115 if (ok) /* no errors */
116 return ok;
117
118 depth = X509_STORE_CTX_get_error_depth(x_store);
119 err = X509_STORE_CTX_get_error(x_store);
120
121 /* check if CA error needs to be ignored */
122 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200123 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
124 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
125 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +0200126 }
127
Emeric Brun81c00f02012-09-21 14:31:21 +0200128 if (target_client(&conn->target)->bind_conf->ca_ignerr & (1ULL << err))
129 return 1;
130
131 return 0;
132 }
133
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200134 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
135 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +0200136
Emeric Brun81c00f02012-09-21 14:31:21 +0200137 /* check if certificate error needs to be ignored */
138 if (target_client(&conn->target)->bind_conf->crt_ignerr & (1ULL << err))
139 return 1;
140
141 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +0200142}
143
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200144#ifdef OPENSSL_NPN_NEGOTIATED
145/* This callback is used so that the server advertises the list of
146 * negociable protocols for NPN.
147 */
148static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
149 unsigned int *len, void *arg)
150{
151 struct bind_conf *conf = arg;
152
153 *data = (const unsigned char *)conf->npn_str;
154 *len = conf->npn_len;
155 return SSL_TLSEXT_ERR_OK;
156}
157#endif
158
Emeric Brunfc0421f2012-09-07 17:30:07 +0200159#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
160/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
161 * warning when no match is found, which implies the default (first) cert
162 * will keep being used.
163 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200164static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, struct bind_conf *s)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200165{
166 const char *servername;
167 const char *wildp = NULL;
168 struct ebmb_node *node;
169 int i;
170 (void)al; /* shut gcc stupid warning */
171
172 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
173 if (!servername)
174 return SSL_TLSEXT_ERR_NOACK;
175
176 for (i = 0; i < trashlen; i++) {
177 if (!servername[i])
178 break;
179 trash[i] = tolower(servername[i]);
180 if (!wildp && (trash[i] == '.'))
181 wildp = &trash[i];
182 }
183 trash[i] = 0;
184
185 /* lookup in full qualified names */
186 node = ebst_lookup(&s->sni_ctx, trash);
187 if (!node) {
188 if (!wildp)
189 return SSL_TLSEXT_ERR_ALERT_WARNING;
190
191 /* lookup in full wildcards names */
192 node = ebst_lookup(&s->sni_w_ctx, wildp);
193 if (!node)
194 return SSL_TLSEXT_ERR_ALERT_WARNING;
195 }
196
197 /* switch ctx */
198 SSL_set_SSL_CTX(ssl, container_of(node, struct sni_ctx, name)->ctx);
199 return SSL_TLSEXT_ERR_OK;
200}
201#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
202
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200203#ifndef OPENSSL_NO_DH
204/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
205 if an error occured, and 0 if parameter not found. */
206int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
207{
208 int ret = -1;
209 BIO *in;
210 DH *dh = NULL;
211
212 in = BIO_new(BIO_s_file());
213 if (in == NULL)
214 goto end;
215
216 if (BIO_read_filename(in, file) <= 0)
217 goto end;
218
219 dh = PEM_read_bio_DHparams(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
220 if (dh) {
221 SSL_CTX_set_tmp_dh(ctx, dh);
222 ret = 1;
223 goto end;
224 }
225
226 ret = 0; /* DH params not found */
227end:
228 if (dh)
229 DH_free(dh);
230
231 if (in)
232 BIO_free(in);
233
234 return ret;
235}
236#endif
237
Emeric Brunfc0421f2012-09-07 17:30:07 +0200238/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
239 * an early error happens and the caller must call SSL_CTX_free() by itelf.
240 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200241int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200242{
243 BIO *in;
244 X509 *x = NULL, *ca;
245 int i, len, err;
246 int ret = -1;
247 int order = 0;
248 X509_NAME *xname;
249 char *str;
250 struct sni_ctx *sc;
251#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
252 STACK_OF(GENERAL_NAME) *names;
253#endif
254
255 in = BIO_new(BIO_s_file());
256 if (in == NULL)
257 goto end;
258
259 if (BIO_read_filename(in, file) <= 0)
260 goto end;
261
262 x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
263 if (x == NULL)
264 goto end;
265
266#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
267 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
268 if (names) {
269 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
270 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
271 if (name->type == GEN_DNS) {
272 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
273 if ((len = strlen(str))) {
274 int j;
275
276 if (*str != '*') {
277 sc = malloc(sizeof(struct sni_ctx) + len + 1);
278 for (j = 0; j < len; j++)
279 sc->name.key[j] = tolower(str[j]);
280 sc->name.key[len] = 0;
281 sc->order = order++;
282 sc->ctx = ctx;
283 ebst_insert(&s->sni_ctx, &sc->name);
284 }
285 else {
286 sc = malloc(sizeof(struct sni_ctx) + len);
287 for (j = 1; j < len; j++)
288 sc->name.key[j-1] = tolower(str[j]);
289 sc->name.key[len-1] = 0;
290 sc->order = order++;
291 sc->ctx = ctx;
292 ebst_insert(&s->sni_w_ctx, &sc->name);
293 }
294 }
295 OPENSSL_free(str);
296 }
297 }
298 }
299 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
300 }
301#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
302
303 xname = X509_get_subject_name(x);
304 i = -1;
305 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
306 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
307 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
308 if ((len = strlen(str))) {
309 int j;
310
311 if (*str != '*') {
312 sc = malloc(sizeof(struct sni_ctx) + len + 1);
313 for (j = 0; j < len; j++)
314 sc->name.key[j] = tolower(str[j]);
315 sc->name.key[len] = 0;
316 sc->order = order++;
317 sc->ctx = ctx;
318 ebst_insert(&s->sni_ctx, &sc->name);
319 }
320 else {
321 sc = malloc(sizeof(struct sni_ctx) + len);
322 for (j = 1; j < len; j++)
323 sc->name.key[j-1] = tolower(str[j]);
324 sc->name.key[len-1] = 0;
325 sc->order = order++;
326 sc->ctx = ctx;
327 ebst_insert(&s->sni_w_ctx, &sc->name);
328 }
329 }
330 OPENSSL_free(str);
331 }
332 }
333
334 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
335 if (!SSL_CTX_use_certificate(ctx, x))
336 goto end;
337
338 if (ctx->extra_certs != NULL) {
339 sk_X509_pop_free(ctx->extra_certs, X509_free);
340 ctx->extra_certs = NULL;
341 }
342
343 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata))) {
344 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
345 X509_free(ca);
346 goto end;
347 }
348 }
349
350 err = ERR_get_error();
351 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
352 /* we successfully reached the last cert in the file */
353 ret = 1;
354 }
355 ERR_clear_error();
356
357end:
358 if (x)
359 X509_free(x);
360
361 if (in)
362 BIO_free(in);
363
364 return ret;
365}
366
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200367static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200368{
369 int ret;
370 SSL_CTX *ctx;
371
372 ctx = SSL_CTX_new(SSLv23_server_method());
373 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200374 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
375 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200376 return 1;
377 }
378
379 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200380 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
381 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200382 SSL_CTX_free(ctx);
383 return 1;
384 }
385
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200386 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200387 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200388 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
389 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200390 if (ret < 0) /* serious error, must do that ourselves */
391 SSL_CTX_free(ctx);
392 return 1;
393 }
394 /* we must not free the SSL_CTX anymore below, since it's already in
395 * the tree, so it will be discovered and cleaned in time.
396 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200397#ifndef OPENSSL_NO_DH
398 ret = ssl_sock_load_dh_params(ctx, path);
399 if (ret < 0) {
400 if (err)
401 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
402 *err ? *err : "", path);
403 return 1;
404 }
405#endif
406
Emeric Brunfc0421f2012-09-07 17:30:07 +0200407#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200408 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200409 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
410 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +0200411 return 1;
412 }
413#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200414 if (!bind_conf->default_ctx)
415 bind_conf->default_ctx = ctx;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200416
417 return 0;
418}
419
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200420int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200421{
422 struct dirent *de;
423 DIR *dir;
424 struct stat buf;
425 int pathlen = 0;
426 char *end, *fp;
427 int cfgerr = 0;
428
429 if (!(dir = opendir(path)))
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200430 return ssl_sock_load_cert_file(path, bind_conf, curproxy, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200431
432 /* strip trailing slashes, including first one */
433 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
434 *end = 0;
435
436 if (end >= path)
437 pathlen = end + 1 - path;
438 fp = malloc(pathlen + 1 + NAME_MAX + 1);
439
440 while ((de = readdir(dir))) {
441 snprintf(fp, pathlen + 1 + NAME_MAX + 1, "%s/%s", path, de->d_name);
442 if (stat(fp, &buf) != 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200443 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
444 err && *err ? *err : "", fp, strerror(errno));
Emeric Brunfc0421f2012-09-07 17:30:07 +0200445 cfgerr++;
446 continue;
447 }
448 if (!S_ISREG(buf.st_mode))
449 continue;
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200450 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, curproxy, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200451 }
452 free(fp);
453 closedir(dir);
454 return cfgerr;
455}
456
457#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
458#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
459#endif
460
461#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
462#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
463#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200464#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
465#define SSL_OP_SINGLE_ECDH_USE 0
466#endif
Emeric Brun2d0c4822012-10-02 13:45:20 +0200467#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
468#define SSL_OP_NO_TICKET 0
469#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200470#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
471#define SSL_OP_NO_COMPRESSION 0
472#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +0200473#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
474#define SSL_OP_NO_TLSv1_1 0
475#endif
476#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
477#define SSL_OP_NO_TLSv1_2 0
478#endif
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200479#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
480#define SSL_OP_SINGLE_DH_USE 0
481#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200482#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
483#define SSL_OP_SINGLE_ECDH_USE 0
484#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200485#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
486#define SSL_MODE_RELEASE_BUFFERS 0
487#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200488int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy *curproxy)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200489{
490 int cfgerr = 0;
491 int ssloptions =
492 SSL_OP_ALL | /* all known workarounds for bugs */
493 SSL_OP_NO_SSLv2 |
494 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200495 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +0200496 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +0200497 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
498 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200499 int sslmode =
500 SSL_MODE_ENABLE_PARTIAL_WRITE |
501 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
502 SSL_MODE_RELEASE_BUFFERS;
503
Emeric Brun89675492012-10-05 13:48:26 +0200504 if (bind_conf->ssl_options & BC_SSL_O_NO_SSLV3)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200505 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brun89675492012-10-05 13:48:26 +0200506 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV10)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200507 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun89675492012-10-05 13:48:26 +0200508 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV11)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200509 ssloptions |= SSL_OP_NO_TLSv1_1;
Emeric Brun89675492012-10-05 13:48:26 +0200510 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV12)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200511 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun89675492012-10-05 13:48:26 +0200512 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
Emeric Brun2d0c4822012-10-02 13:45:20 +0200513 ssloptions |= SSL_OP_NO_TICKET;
Emeric Brun2cb7ae52012-10-05 14:14:21 +0200514 if (bind_conf->ssl_options & BC_SSL_O_USE_SSLV3)
515 SSL_CTX_set_ssl_version(ctx, SSLv3_server_method());
516 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV10)
517 SSL_CTX_set_ssl_version(ctx, TLSv1_server_method());
518#if SSL_OP_NO_TLSv1_1
519 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV11)
520 SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method());
521#endif
522#if SSL_OP_NO_TLSv1_2
523 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV12)
524 SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method());
525#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200526
527 SSL_CTX_set_options(ctx, ssloptions);
528 SSL_CTX_set_mode(ctx, sslmode);
Emeric Brune64aef12012-09-21 13:15:06 +0200529 SSL_CTX_set_verify(ctx, bind_conf->verify ? bind_conf->verify : SSL_VERIFY_NONE, ssl_sock_verifycbk);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200530 if (bind_conf->verify & SSL_VERIFY_PEER) {
Emeric Brunfb510ea2012-10-05 12:00:26 +0200531 if (bind_conf->ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200532 /* load CAfile to verify */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200533 if (!SSL_CTX_load_verify_locations(ctx, bind_conf->ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200534 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200535 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200536 cfgerr++;
537 }
538 /* set CA names fo client cert request, function returns void */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200539 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(bind_conf->ca_file));
Emeric Brund94b3fe2012-09-20 18:23:56 +0200540 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200541#ifdef X509_V_FLAG_CRL_CHECK
Emeric Brunfb510ea2012-10-05 12:00:26 +0200542 if (bind_conf->crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200543 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
544
Emeric Brunfb510ea2012-10-05 12:00:26 +0200545 if (!store || !X509_STORE_load_locations(store, bind_conf->crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200546 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200547 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200548 cfgerr++;
549 }
Emeric Brun561e5742012-10-02 15:20:55 +0200550 else {
551 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
552 }
Emeric Brund94b3fe2012-09-20 18:23:56 +0200553 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200554#endif
Emeric Brund94b3fe2012-09-20 18:23:56 +0200555 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200556
557 shared_context_set_cache(ctx);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200558 if (bind_conf->ciphers &&
559 !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200560 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 +0200561 curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200562 cfgerr++;
563 }
564
565 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200566#ifdef OPENSSL_NPN_NEGOTIATED
567 if (bind_conf->npn_str)
568 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
569#endif
570
Emeric Brunfc0421f2012-09-07 17:30:07 +0200571#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
572 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200573 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200574#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200575#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
576 if (bind_conf->ecdhe) {
577 int i;
578 EC_KEY *ecdh;
579
580 i = OBJ_sn2nid(bind_conf->ecdhe);
581 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
582 Alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
583 curproxy->id, bind_conf->ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
584 cfgerr++;
585 }
586 else {
587 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
588 EC_KEY_free(ecdh);
589 }
590 }
591#endif
592
Emeric Brunfc0421f2012-09-07 17:30:07 +0200593 return cfgerr;
594}
595
Emeric Brun94324a42012-10-11 14:00:19 +0200596/* prepare ssl context from servers options. Returns an error count */
597int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
598{
599 int cfgerr = 0;
600 int options =
601 SSL_OP_ALL | /* all known workarounds for bugs */
602 SSL_OP_NO_SSLv2 |
603 SSL_OP_NO_COMPRESSION;
604 int mode =
605 SSL_MODE_ENABLE_PARTIAL_WRITE |
606 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
607 SSL_MODE_RELEASE_BUFFERS;
608
609 /* Initiate SSL context for current server */
610 srv->ssl_ctx.reused_sess = NULL;
611 if (srv->use_ssl)
612 srv->xprt = &ssl_sock;
613 if (srv->check.use_ssl)
614 srv->check.xprt = &ssl_sock;
615
616 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
617 if (!srv->ssl_ctx.ctx) {
618 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
619 proxy_type_str(curproxy), curproxy->id,
620 srv->id);
621 cfgerr++;
622 return cfgerr;
623 }
624
625
626 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
627 options |= SSL_OP_NO_SSLv3;
628 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
629 options |= SSL_OP_NO_TLSv1;
630 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
631 options |= SSL_OP_NO_TLSv1_1;
632 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
633 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200634 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
635 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200636 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
637 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
638 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
639 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
640#if SSL_OP_NO_TLSv1_1
641 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
642 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
643#endif
644#if SSL_OP_NO_TLSv1_2
645 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
646 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
647#endif
648
649 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
650 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Emeric Brunef42d922012-10-11 16:11:36 +0200651 SSL_CTX_set_verify(srv->ssl_ctx.ctx, srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE, NULL);
652 if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
653 if (srv->ssl_ctx.ca_file) {
654 /* load CAfile to verify */
655 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
656 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
657 curproxy->id, srv->id,
658 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
659 cfgerr++;
660 }
661 }
662#ifdef X509_V_FLAG_CRL_CHECK
663 if (srv->ssl_ctx.crl_file) {
664 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
665
666 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
667 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
668 curproxy->id, srv->id,
669 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
670 cfgerr++;
671 }
672 else {
673 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
674 }
675 }
676#endif
677 }
678
Emeric Brun94324a42012-10-11 14:00:19 +0200679 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
680 if (srv->ssl_ctx.ciphers &&
681 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
682 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
683 curproxy->id, srv->id,
684 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
685 cfgerr++;
686 }
687
688 return cfgerr;
689}
690
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200691/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200692 * be NULL, in which case nothing is done. Returns the number of errors
693 * encountered.
694 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200695int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200696{
697 struct ebmb_node *node;
698 struct sni_ctx *sni;
699 int err = 0;
700
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200701 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200702 return 0;
703
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200704 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200705 while (node) {
706 sni = ebmb_entry(node, struct sni_ctx, name);
707 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200708 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200709 node = ebmb_next(node);
710 }
711
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200712 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200713 while (node) {
714 sni = ebmb_entry(node, struct sni_ctx, name);
715 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200716 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200717 node = ebmb_next(node);
718 }
719 return err;
720}
721
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200722/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200723 * be NULL, in which case nothing is done. The default_ctx is nullified too.
724 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200725void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200726{
727 struct ebmb_node *node, *back;
728 struct sni_ctx *sni;
729
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200730 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200731 return;
732
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200733 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200734 while (node) {
735 sni = ebmb_entry(node, struct sni_ctx, name);
736 back = ebmb_next(node);
737 ebmb_delete(node);
738 if (!sni->order) /* only free the CTX on its first occurrence */
739 SSL_CTX_free(sni->ctx);
740 free(sni);
741 node = back;
742 }
743
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200744 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200745 while (node) {
746 sni = ebmb_entry(node, struct sni_ctx, name);
747 back = ebmb_next(node);
748 ebmb_delete(node);
749 if (!sni->order) /* only free the CTX on its first occurrence */
750 SSL_CTX_free(sni->ctx);
751 free(sni);
752 node = back;
753 }
754
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200755 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +0200756}
757
Emeric Brun46591952012-05-18 15:47:34 +0200758/*
759 * This function is called if SSL * context is not yet allocated. The function
760 * is designed to be called before any other data-layer operation and sets the
761 * handshake flag on the connection. It is safe to call it multiple times.
762 * It returns 0 on success and -1 in error case.
763 */
764static int ssl_sock_init(struct connection *conn)
765{
766 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200767 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200768 return 0;
769
Willy Tarreau403edff2012-09-06 11:58:37 +0200770 if (global.maxsslconn && sslconns >= global.maxsslconn)
771 return -1;
772
Emeric Brun46591952012-05-18 15:47:34 +0200773 /* If it is in client mode initiate SSL session
774 in connect state otherwise accept state */
775 if (target_srv(&conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200776 /* Alloc a new SSL session ctx */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200777 conn->xprt_ctx = SSL_new(target_srv(&conn->target)->ssl_ctx.ctx);
778 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200779 return -1;
780
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200781 SSL_set_connect_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200782 if (target_srv(&conn->target)->ssl_ctx.reused_sess)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200783 SSL_set_session(conn->xprt_ctx, target_srv(&conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +0200784
785 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200786 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200787
788 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200789 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200790
791 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200792 return 0;
793 }
794 else if (target_client(&conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200795 /* Alloc a new SSL session ctx */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200796 conn->xprt_ctx = SSL_new(target_client(&conn->target)->bind_conf->default_ctx);
797 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200798 return -1;
799
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200800 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200801
802 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200803 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200804
Emeric Brune1f38db2012-09-03 20:36:47 +0200805 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200806 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +0200807
Emeric Brun46591952012-05-18 15:47:34 +0200808 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200809 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200810
811 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200812 return 0;
813 }
814 /* don't know how to handle such a target */
815 return -1;
816}
817
818
819/* This is the callback which is used when an SSL handshake is pending. It
820 * updates the FD status if it wants some polling before being called again.
821 * It returns 0 if it fails in a fatal way or needs to poll to go further,
822 * otherwise it returns non-zero and removes itself from the connection's
823 * flags (the bit is provided in <flag> by the caller).
824 */
825int ssl_sock_handshake(struct connection *conn, unsigned int flag)
826{
827 int ret;
828
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200829 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200830 goto out_error;
831
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200832 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200833 if (ret != 1) {
834 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200835 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +0200836
837 if (ret == SSL_ERROR_WANT_WRITE) {
838 /* SSL handshake needs to write, L4 connection may not be ready */
839 __conn_sock_stop_recv(conn);
840 __conn_sock_poll_send(conn);
841 return 0;
842 }
843 else if (ret == SSL_ERROR_WANT_READ) {
844 /* SSL handshake needs to read, L4 connection is ready */
845 if (conn->flags & CO_FL_WAIT_L4_CONN)
846 conn->flags &= ~CO_FL_WAIT_L4_CONN;
847 __conn_sock_stop_send(conn);
848 __conn_sock_poll_recv(conn);
849 return 0;
850 }
Willy Tarreau89230192012-09-28 20:22:13 +0200851 else if (ret == SSL_ERROR_SYSCALL) {
852 /* if errno is null, then connection was successfully established */
853 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
854 conn->flags &= ~CO_FL_WAIT_L4_CONN;
855 goto out_error;
856 }
Emeric Brun46591952012-05-18 15:47:34 +0200857 else {
858 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +0200859 /* Note: OpenSSL may leave unread bytes in the socket's
860 * buffer, causing an RST to be emitted upon close() on
861 * TCP sockets. We first try to drain possibly pending
862 * data to avoid this as much as possible.
863 */
864 ret = recv(conn->t.sock.fd, trash, trashlen, MSG_NOSIGNAL|MSG_DONTWAIT);
Emeric Brun46591952012-05-18 15:47:34 +0200865 goto out_error;
866 }
867 }
868
869 /* Handshake succeeded */
870 if (target_srv(&conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200871 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +0200872 /* check if session was reused, if not store current session on server for reuse */
873 if (target_srv(&conn->target)->ssl_ctx.reused_sess)
874 SSL_SESSION_free(target_srv(&conn->target)->ssl_ctx.reused_sess);
875
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200876 target_srv(&conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200877 }
878 }
879
880 /* The connection is now established at both layers, it's time to leave */
881 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
882 return 1;
883
884 out_error:
Emeric Brun9fa89732012-10-04 17:09:56 +0200885 /* free resumed session if exists */
886 if (target_srv(&conn->target) && target_srv(&conn->target)->ssl_ctx.reused_sess) {
887 SSL_SESSION_free(target_srv(&conn->target)->ssl_ctx.reused_sess);
888 target_srv(&conn->target)->ssl_ctx.reused_sess = NULL;
889 }
890
Emeric Brun46591952012-05-18 15:47:34 +0200891 /* Fail on all other handshake errors */
892 conn->flags |= CO_FL_ERROR;
893 conn->flags &= ~flag;
894 return 0;
895}
896
897/* Receive up to <count> bytes from connection <conn>'s socket and store them
898 * into buffer <buf>. The caller must ensure that <count> is always smaller
899 * than the buffer's size. Only one call to recv() is performed, unless the
900 * buffer wraps, in which case a second call may be performed. The connection's
901 * flags are updated with whatever special event is detected (error, read0,
902 * empty). The caller is responsible for taking care of those events and
903 * avoiding the call if inappropriate. The function does not call the
904 * connection's polling update function, so the caller is responsible for this.
905 */
906static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
907{
908 int ret, done = 0;
909 int try = count;
910
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200911 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200912 goto out_error;
913
914 if (conn->flags & CO_FL_HANDSHAKE)
915 /* a handshake was requested */
916 return 0;
917
918 /* compute the maximum block size we can read at once. */
919 if (buffer_empty(buf)) {
920 /* let's realign the buffer to optimize I/O */
921 buf->p = buf->data;
922 }
923 else if (buf->data + buf->o < buf->p &&
924 buf->p + buf->i < buf->data + buf->size) {
925 /* remaining space wraps at the end, with a moving limit */
926 if (try > buf->data + buf->size - (buf->p + buf->i))
927 try = buf->data + buf->size - (buf->p + buf->i);
928 }
929
930 /* read the largest possible block. For this, we perform only one call
931 * to recv() unless the buffer wraps and we exactly fill the first hunk,
932 * in which case we accept to do it once again. A new attempt is made on
933 * EINTR too.
934 */
935 while (try) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200936 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +0200937 if (conn->flags & CO_FL_ERROR) {
938 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
939 break;
940 }
Emeric Brun46591952012-05-18 15:47:34 +0200941 if (ret > 0) {
942 buf->i += ret;
943 done += ret;
944 if (ret < try)
945 break;
946 count -= ret;
947 try = count;
948 }
949 else if (ret == 0) {
950 goto read0;
951 }
952 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200953 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +0200954 if (ret == SSL_ERROR_WANT_WRITE) {
955 /* handshake is running, and it needs to poll for a write event */
956 conn->flags |= CO_FL_SSL_WAIT_HS;
957 __conn_sock_poll_send(conn);
958 break;
959 }
960 else if (ret == SSL_ERROR_WANT_READ) {
961 /* we need to poll for retry a read later */
962 __conn_data_poll_recv(conn);
963 break;
964 }
965 /* otherwise it's a real error */
966 goto out_error;
967 }
968 }
969 return done;
970
971 read0:
972 conn_sock_read0(conn);
973 return done;
974 out_error:
975 conn->flags |= CO_FL_ERROR;
976 return done;
977}
978
979
980/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
981 * <flags> may contain MSG_MORE to make the system hold on without sending
982 * data too fast, but this flag is ignored at the moment.
983 * Only one call to send() is performed, unless the buffer wraps, in which case
984 * a second call may be performed. The connection's flags are updated with
985 * whatever special event is detected (error, empty). The caller is responsible
986 * for taking care of those events and avoiding the call if inappropriate. The
987 * function does not call the connection's polling update function, so the caller
988 * is responsible for this.
989 */
990static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
991{
992 int ret, try, done;
993
994 done = 0;
995
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200996 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200997 goto out_error;
998
999 if (conn->flags & CO_FL_HANDSHAKE)
1000 /* a handshake was requested */
1001 return 0;
1002
1003 /* send the largest possible block. For this we perform only one call
1004 * to send() unless the buffer wraps and we exactly fill the first hunk,
1005 * in which case we accept to do it once again.
1006 */
1007 while (buf->o) {
1008 try = buf->o;
1009 /* outgoing data may wrap at the end */
1010 if (buf->data + try > buf->p)
1011 try = buf->data + try - buf->p;
1012
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001013 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001014 if (conn->flags & CO_FL_ERROR) {
1015 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
1016 break;
1017 }
Emeric Brun46591952012-05-18 15:47:34 +02001018 if (ret > 0) {
1019 buf->o -= ret;
1020 done += ret;
1021
1022 if (likely(!buffer_len(buf)))
1023 /* optimize data alignment in the buffer */
1024 buf->p = buf->data;
1025
1026 /* if the system buffer is full, don't insist */
1027 if (ret < try)
1028 break;
1029 }
1030 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001031 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001032 if (ret == SSL_ERROR_WANT_WRITE) {
1033 /* we need to poll to retry a write later */
1034 __conn_data_poll_send(conn);
1035 break;
1036 }
1037 else if (ret == SSL_ERROR_WANT_READ) {
1038 /* handshake is running, and
1039 it needs to poll for a read event,
1040 write polling must be disabled cause
1041 we are sure we can't write anything more
1042 before handshake re-performed */
1043 conn->flags |= CO_FL_SSL_WAIT_HS;
1044 __conn_sock_poll_recv(conn);
1045 break;
1046 }
1047 goto out_error;
1048 }
1049 }
1050 return done;
1051
1052 out_error:
1053 conn->flags |= CO_FL_ERROR;
1054 return done;
1055}
1056
1057
1058static void ssl_sock_close(struct connection *conn) {
1059
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001060 if (conn->xprt_ctx) {
1061 SSL_free(conn->xprt_ctx);
1062 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001063 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001064 }
Emeric Brun46591952012-05-18 15:47:34 +02001065}
1066
1067/* This function tries to perform a clean shutdown on an SSL connection, and in
1068 * any case, flags the connection as reusable if no handshake was in progress.
1069 */
1070static void ssl_sock_shutw(struct connection *conn, int clean)
1071{
1072 if (conn->flags & CO_FL_HANDSHAKE)
1073 return;
1074 /* no handshake was in progress, try a clean ssl shutdown */
1075 if (clean)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001076 SSL_shutdown(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001077
1078 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001079 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001080}
1081
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001082/* used for logging, may be changed for a sample fetch later */
1083const char *ssl_sock_get_cipher_name(struct connection *conn)
1084{
1085 if (!conn->xprt && !conn->xprt_ctx)
1086 return NULL;
1087 return SSL_get_cipher_name(conn->xprt_ctx);
1088}
1089
1090/* used for logging, may be changed for a sample fetch later */
1091const char *ssl_sock_get_proto_version(struct connection *conn)
1092{
1093 if (!conn->xprt && !conn->xprt_ctx)
1094 return NULL;
1095 return SSL_get_version(conn->xprt_ctx);
1096}
1097
Willy Tarreau8d598402012-10-22 17:58:39 +02001098/* Extract a serial from a cert, and copy it to a chunk.
1099 * Returns 1 if serial is found and copied, 0 if no serial found and
1100 * -1 if output is not large enough.
1101 */
1102static int
1103ssl_sock_get_serial(X509 *crt, struct chunk *out)
1104{
1105 ASN1_INTEGER *serial;
1106
1107 serial = X509_get_serialNumber(crt);
1108 if (!serial)
1109 return 0;
1110
1111 if (out->size < serial->length)
1112 return -1;
1113
1114 memcpy(out->str, serial->data, serial->length);
1115 out->len = serial->length;
1116 return 1;
1117}
1118
Willy Tarreau7875d092012-09-10 08:20:03 +02001119/***** Below are some sample fetching functions for ACL/patterns *****/
1120
Emeric Brune64aef12012-09-21 13:15:06 +02001121/* boolean, returns true if client cert was present */
1122static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001123smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1124 const struct arg *args, struct sample *smp)
Emeric Brune64aef12012-09-21 13:15:06 +02001125{
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001126 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001127 return 0;
1128
1129 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1130 smp->flags |= SMP_F_MAY_CHANGE;
1131 return 0;
1132 }
1133
1134 smp->flags = 0;
1135 smp->type = SMP_T_BOOL;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001136 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn.xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001137
1138 return 1;
1139}
1140
Willy Tarreau8d598402012-10-22 17:58:39 +02001141/* bin, returns serial in a binary chunk */
1142static int
1143smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1144 const struct arg *args, struct sample *smp)
1145{
1146 X509 *crt = NULL;
1147 int ret = 0;
1148 struct chunk *smp_trash;
1149
1150 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1151 return 0;
1152
1153 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1154 smp->flags |= SMP_F_MAY_CHANGE;
1155 return 0;
1156 }
1157
1158 /* SSL_get_peer_certificate, it increase X509 * ref count */
1159 crt = SSL_get_peer_certificate(l4->si[0].conn.xprt_ctx);
1160 if (!crt)
1161 goto out;
1162
1163 smp_trash = sample_get_trash_chunk();
1164 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1165 goto out;
1166
1167 smp->data.str = *smp_trash;
1168 smp->type = SMP_T_BIN;
1169 ret = 1;
1170out:
1171 if (crt)
1172 X509_free(crt);
1173 return ret;
1174}
Emeric Brune64aef12012-09-21 13:15:06 +02001175
Emeric Bruna7359fd2012-10-17 15:03:11 +02001176/* integer, returns the client certificate version */
1177static int
1178smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1179 const struct arg *args, struct sample *smp)
1180{
1181 X509 *crt;
1182
1183 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1184 return 0;
1185
1186 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1187 smp->flags |= SMP_F_MAY_CHANGE;
1188 return 0;
1189 }
1190
1191 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
1192 crt = SSL_get_peer_certificate(l4->si[0].conn.xprt_ctx);
1193 if (!crt)
1194 return 0;
1195
1196 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1197 X509_free(crt);
1198 smp->type = SMP_T_UINT;
1199
1200 return 1;
1201}
1202
Emeric Brun2525b6b2012-10-18 15:59:43 +02001203/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02001204static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001205smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau7875d092012-09-10 08:20:03 +02001206 const struct arg *args, struct sample *smp)
1207{
1208 smp->type = SMP_T_BOOL;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001209 smp->data.uint = (l4->si[0].conn.xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02001210 return 1;
1211}
1212
Emeric Brun2525b6b2012-10-18 15:59:43 +02001213/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02001214static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001215smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1216 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02001217{
1218#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1219 smp->type = SMP_T_BOOL;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001220 smp->data.uint = (l4->si[0].conn.xprt == &ssl_sock) &&
1221 l4->si[0].conn.xprt_ctx &&
1222 SSL_get_servername(l4->si[0].conn.xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02001223 return 1;
1224#else
1225 return 0;
1226#endif
1227}
1228
Willy Tarreau8d598402012-10-22 17:58:39 +02001229/* bin, returns serial in a binary chunk */
1230static int
1231smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1232 const struct arg *args, struct sample *smp)
1233{
1234 X509 *crt = NULL;
1235 int ret = 0;
1236 struct chunk *smp_trash;
1237
1238 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1239 return 0;
1240
1241 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1242 smp->flags |= SMP_F_MAY_CHANGE;
1243 return 0;
1244 }
1245
1246 crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
1247 if (!crt)
1248 goto out;
1249
1250 smp_trash = sample_get_trash_chunk();
1251 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1252 goto out;
1253
1254 smp->data.str = *smp_trash;
1255 smp->type = SMP_T_BIN;
1256 ret = 1;
1257out:
1258 return ret;
1259}
1260
Emeric Bruna7359fd2012-10-17 15:03:11 +02001261/* integer, returns the frontend certificate version */
1262static int
1263smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1264 const struct arg *args, struct sample *smp)
1265{
1266 X509 *crt;
1267
1268 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
1269 return 0;
1270
1271 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1272 smp->flags |= SMP_F_MAY_CHANGE;
1273 return 0;
1274 }
1275
1276 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
1277 crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
1278 if (!crt)
1279 return 0;
1280
1281 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1282 smp->type = SMP_T_UINT;
1283
1284 return 1;
1285}
1286
Emeric Brun589fcad2012-10-16 14:13:26 +02001287static int
1288smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1289 const struct arg *args, struct sample *smp)
1290{
1291 smp->flags = 0;
1292
1293 if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
1294 return 0;
1295
1296 smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn.xprt_ctx);
1297 if (!smp->data.str.str)
1298 return 0;
1299
1300 smp->type = SMP_T_CSTR;
1301 smp->data.str.len = strlen(smp->data.str.str);
1302
1303 return 1;
1304}
1305
1306static int
1307smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1308 const struct arg *args, struct sample *smp)
1309{
1310 smp->flags = 0;
1311
1312 if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
1313 return 0;
1314
1315 if (!SSL_get_cipher_bits(l4->si[0].conn.xprt_ctx, (int *)&smp->data.uint))
1316 return 0;
1317
1318 smp->type = SMP_T_UINT;
1319
1320 return 1;
1321}
1322
1323static int
1324smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1325 const struct arg *args, struct sample *smp)
1326{
1327 smp->flags = 0;
1328
1329 if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
1330 return 0;
1331
1332 smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn.xprt_ctx, NULL);
1333 if (!smp->data.uint)
1334 return 0;
1335
1336 smp->type = SMP_T_UINT;
1337
1338 return 1;
1339}
1340
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001341#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02001342static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001343smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1344 const struct arg *args, struct sample *smp)
Willy Tarreaua33c6542012-10-15 13:19:06 +02001345{
Willy Tarreaua33c6542012-10-15 13:19:06 +02001346 smp->flags = 0;
1347 smp->type = SMP_T_CSTR;
1348
1349 if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
1350 return 0;
1351
1352 smp->data.str.str = NULL;
1353 SSL_get0_next_proto_negotiated(l4->si[0].conn.xprt_ctx,
1354 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
1355
1356 if (!smp->data.str.str)
1357 return 0;
1358
1359 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02001360}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001361#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02001362
1363static int
Emeric Brun589fcad2012-10-16 14:13:26 +02001364smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1365 const struct arg *args, struct sample *smp)
1366{
1367 smp->flags = 0;
1368
1369 if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
1370 return 0;
1371
1372 smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn.xprt_ctx);
1373 if (!smp->data.str.str)
1374 return 0;
1375
1376 smp->type = SMP_T_CSTR;
1377 smp->data.str.len = strlen(smp->data.str.str);
1378
1379 return 1;
1380}
1381
1382static int
Emeric Brunfe68f682012-10-16 14:59:28 +02001383smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1384 const struct arg *args, struct sample *smp)
1385{
1386#if OPENSSL_VERSION_NUMBER > 0x0090800fL
1387 SSL_SESSION *sess;
1388
1389 smp->flags = 0;
1390 smp->type = SMP_T_CBIN;
1391
1392 if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
1393 return 0;
1394
1395 sess = SSL_get_session(l4->si[0].conn.xprt_ctx);
1396 if (!sess)
1397 return 0;
1398
1399 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
1400 if (!smp->data.str.str || !&smp->data.str.len)
1401 return 0;
1402
1403 return 1;
1404#else
1405 return 0;
1406#endif
1407}
1408
1409static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001410smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1411 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02001412{
1413#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1414 smp->flags = 0;
1415 smp->type = SMP_T_CSTR;
1416
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001417 if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
Willy Tarreau7875d092012-09-10 08:20:03 +02001418 return 0;
1419
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001420 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 +02001421 if (!smp->data.str.str)
1422 return 0;
1423
Willy Tarreau7875d092012-09-10 08:20:03 +02001424 smp->data.str.len = strlen(smp->data.str.str);
1425 return 1;
1426#else
1427 return 0;
1428#endif
1429}
1430
Emeric Brun2525b6b2012-10-18 15:59:43 +02001431/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02001432static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001433smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02001434 const struct arg *args, struct sample *smp)
1435{
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001436 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02001437 return 0;
1438
1439 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1440 smp->flags = SMP_F_MAY_CHANGE;
1441 return 0;
1442 }
1443
1444 smp->type = SMP_T_UINT;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001445 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn.xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02001446 smp->flags = 0;
1447
1448 return 1;
1449}
1450
Emeric Brun2525b6b2012-10-18 15:59:43 +02001451/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02001452static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001453smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02001454 const struct arg *args, struct sample *smp)
1455{
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001456 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02001457 return 0;
1458
1459 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1460 smp->flags = SMP_F_MAY_CHANGE;
1461 return 0;
1462 }
1463
1464 smp->type = SMP_T_UINT;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001465 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn.xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02001466 smp->flags = 0;
1467
1468 return 1;
1469}
1470
Emeric Brun2525b6b2012-10-18 15:59:43 +02001471/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02001472static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001473smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1474 const struct arg *args, struct sample *smp)
Emeric Brunf282a812012-09-21 15:27:54 +02001475{
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001476 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02001477 return 0;
1478
1479 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1480 smp->flags = SMP_F_MAY_CHANGE;
1481 return 0;
1482 }
1483
1484 smp->type = SMP_T_UINT;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001485 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn.xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02001486 smp->flags = 0;
1487
1488 return 1;
1489}
1490
Emeric Brun2525b6b2012-10-18 15:59:43 +02001491/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02001492static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001493smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1494 const struct arg *args, struct sample *smp)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02001495{
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001496 if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02001497 return 0;
1498
1499 if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
1500 smp->flags = SMP_F_MAY_CHANGE;
1501 return 0;
1502 }
1503
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001504 if (!l4->si[0].conn.xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02001505 return 0;
1506
1507 smp->type = SMP_T_UINT;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001508 smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn.xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02001509 smp->flags = 0;
1510
1511 return 1;
1512}
1513
Emeric Brunfb510ea2012-10-05 12:00:26 +02001514/* parse the "ca-file" bind keyword */
1515static 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 +02001516{
1517 if (!*args[cur_arg + 1]) {
1518 if (err)
1519 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
1520 return ERR_ALERT | ERR_FATAL;
1521 }
1522
Emeric Brunef42d922012-10-11 16:11:36 +02001523 if ((*args[cur_arg + 1] != '/') && global.ca_base)
1524 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
1525 else
1526 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02001527
Emeric Brund94b3fe2012-09-20 18:23:56 +02001528 return 0;
1529}
1530
Willy Tarreau79eeafa2012-09-14 07:53:05 +02001531/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001532static 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 +02001533{
1534 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001535 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02001536 return ERR_ALERT | ERR_FATAL;
1537 }
1538
Emeric Brun76d88952012-10-05 15:47:31 +02001539 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02001540 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02001541 return 0;
1542}
1543
1544/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001545static 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 +02001546{
Emeric Brunc8e8d122012-10-02 18:42:10 +02001547 char path[PATH_MAX];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02001548 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001549 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02001550 return ERR_ALERT | ERR_FATAL;
1551 }
1552
Emeric Brunc8e8d122012-10-02 18:42:10 +02001553 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
1554 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > PATH_MAX) {
1555 memprintf(err, "'%s' : path too long", args[cur_arg]);
1556 return ERR_ALERT | ERR_FATAL;
1557 }
1558 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
1559 if (ssl_sock_load_cert(path, conf, px, err) > 0)
1560 return ERR_ALERT | ERR_FATAL;
1561
1562 return 0;
1563 }
1564
Willy Tarreau4348fad2012-09-20 16:48:07 +02001565 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02001566 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02001567
1568 return 0;
1569}
1570
Emeric Brunfb510ea2012-10-05 12:00:26 +02001571/* parse the "crl-file" bind keyword */
1572static 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 +02001573{
Emeric Brun051cdab2012-10-02 19:25:50 +02001574#ifndef X509_V_FLAG_CRL_CHECK
1575 if (err)
1576 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
1577 return ERR_ALERT | ERR_FATAL;
1578#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02001579 if (!*args[cur_arg + 1]) {
1580 if (err)
1581 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
1582 return ERR_ALERT | ERR_FATAL;
1583 }
Emeric Brun2b58d042012-09-20 17:10:03 +02001584
Emeric Brunef42d922012-10-11 16:11:36 +02001585 if ((*args[cur_arg + 1] != '/') && global.ca_base)
1586 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
1587 else
1588 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02001589
Emeric Brun2b58d042012-09-20 17:10:03 +02001590 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02001591#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02001592}
1593
1594/* parse the "ecdhe" bind keyword keywords */
1595static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1596{
1597#if OPENSSL_VERSION_NUMBER < 0x0090800fL
1598 if (err)
1599 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
1600 return ERR_ALERT | ERR_FATAL;
1601#elif defined(OPENSSL_NO_ECDH)
1602 if (err)
1603 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
1604 return ERR_ALERT | ERR_FATAL;
1605#else
1606 if (!*args[cur_arg + 1]) {
1607 if (err)
1608 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
1609 return ERR_ALERT | ERR_FATAL;
1610 }
1611
1612 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02001613
1614 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02001615#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02001616}
1617
Emeric Brun81c00f02012-09-21 14:31:21 +02001618/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
1619static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1620{
1621 int code;
1622 char *p = args[cur_arg + 1];
1623 unsigned long long *ignerr = &conf->crt_ignerr;
1624
1625 if (!*p) {
1626 if (err)
1627 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
1628 return ERR_ALERT | ERR_FATAL;
1629 }
1630
1631 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
1632 ignerr = &conf->ca_ignerr;
1633
1634 if (strcmp(p, "all") == 0) {
1635 *ignerr = ~0ULL;
1636 return 0;
1637 }
1638
1639 while (p) {
1640 code = atoi(p);
1641 if ((code <= 0) || (code > 63)) {
1642 if (err)
1643 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
1644 args[cur_arg], code, args[cur_arg + 1]);
1645 return ERR_ALERT | ERR_FATAL;
1646 }
1647 *ignerr |= 1ULL << code;
1648 p = strchr(p, ',');
1649 if (p)
1650 p++;
1651 }
1652
Emeric Brun2cb7ae52012-10-05 14:14:21 +02001653 return 0;
1654}
1655
1656/* parse the "force-sslv3" bind keyword */
1657static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1658{
1659 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
1660 return 0;
1661}
1662
1663/* parse the "force-tlsv10" bind keyword */
1664static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1665{
1666 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02001667 return 0;
1668}
1669
Emeric Brun2cb7ae52012-10-05 14:14:21 +02001670/* parse the "force-tlsv11" bind keyword */
1671static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1672{
1673#if SSL_OP_NO_TLSv1_1
1674 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
1675 return 0;
1676#else
1677 if (err)
1678 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
1679 return ERR_ALERT | ERR_FATAL;
1680#endif
1681}
1682
1683/* parse the "force-tlsv12" bind keyword */
1684static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1685{
1686#if SSL_OP_NO_TLSv1_2
1687 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
1688 return 0;
1689#else
1690 if (err)
1691 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
1692 return ERR_ALERT | ERR_FATAL;
1693#endif
1694}
1695
1696
Emeric Brun2d0c4822012-10-02 13:45:20 +02001697/* parse the "no-tls-tickets" bind keyword */
1698static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1699{
Emeric Brun89675492012-10-05 13:48:26 +02001700 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02001701 return 0;
1702}
1703
Emeric Brun2d0c4822012-10-02 13:45:20 +02001704
Emeric Brun9b3009b2012-10-05 11:55:06 +02001705/* parse the "no-sslv3" bind keyword */
1706static 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 +02001707{
Emeric Brun89675492012-10-05 13:48:26 +02001708 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02001709 return 0;
1710}
1711
Emeric Brun9b3009b2012-10-05 11:55:06 +02001712/* parse the "no-tlsv10" bind keyword */
1713static 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 +02001714{
Emeric Brun89675492012-10-05 13:48:26 +02001715 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02001716 return 0;
1717}
1718
Emeric Brun9b3009b2012-10-05 11:55:06 +02001719/* parse the "no-tlsv11" bind keyword */
1720static 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 +02001721{
Emeric Brun89675492012-10-05 13:48:26 +02001722 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02001723 return 0;
1724}
1725
Emeric Brun9b3009b2012-10-05 11:55:06 +02001726/* parse the "no-tlsv12" bind keyword */
1727static 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 +02001728{
Emeric Brun89675492012-10-05 13:48:26 +02001729 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02001730 return 0;
1731}
1732
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001733/* parse the "npn" bind keyword */
1734static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1735{
1736#ifdef OPENSSL_NPN_NEGOTIATED
1737 char *p1, *p2;
1738
1739 if (!*args[cur_arg + 1]) {
1740 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
1741 return ERR_ALERT | ERR_FATAL;
1742 }
1743
1744 free(conf->npn_str);
1745
1746 /* the NPN string is built as a suite of (<len> <name>)* */
1747 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
1748 conf->npn_str = calloc(1, conf->npn_len);
1749 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
1750
1751 /* replace commas with the name length */
1752 p1 = conf->npn_str;
1753 p2 = p1 + 1;
1754 while (1) {
1755 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
1756 if (!p2)
1757 p2 = p1 + 1 + strlen(p1 + 1);
1758
1759 if (p2 - (p1 + 1) > 255) {
1760 *p2 = '\0';
1761 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
1762 return ERR_ALERT | ERR_FATAL;
1763 }
1764
1765 *p1 = p2 - (p1 + 1);
1766 p1 = p2;
1767
1768 if (!*p2)
1769 break;
1770
1771 *(p2++) = '\0';
1772 }
1773 return 0;
1774#else
1775 if (err)
1776 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
1777 return ERR_ALERT | ERR_FATAL;
1778#endif
1779}
1780
Willy Tarreau79eeafa2012-09-14 07:53:05 +02001781/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001782static 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 +02001783{
Willy Tarreau81796be2012-09-22 19:11:47 +02001784 struct listener *l;
1785
Willy Tarreau4348fad2012-09-20 16:48:07 +02001786 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02001787
1788 if (global.listen_default_ciphers && !conf->ciphers)
1789 conf->ciphers = strdup(global.listen_default_ciphers);
1790
Willy Tarreau81796be2012-09-22 19:11:47 +02001791 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001792 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02001793
Willy Tarreau79eeafa2012-09-14 07:53:05 +02001794 return 0;
1795}
1796
Emeric Brund94b3fe2012-09-20 18:23:56 +02001797/* parse the "verify" bind keyword */
1798static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1799{
1800 if (!*args[cur_arg + 1]) {
1801 if (err)
1802 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
1803 return ERR_ALERT | ERR_FATAL;
1804 }
1805
1806 if (strcmp(args[cur_arg + 1], "none") == 0)
1807 conf->verify = SSL_VERIFY_NONE;
1808 else if (strcmp(args[cur_arg + 1], "optional") == 0)
1809 conf->verify = SSL_VERIFY_PEER;
1810 else if (strcmp(args[cur_arg + 1], "required") == 0)
1811 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
1812 else {
1813 if (err)
1814 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
1815 args[cur_arg], args[cur_arg + 1]);
1816 return ERR_ALERT | ERR_FATAL;
1817 }
1818
1819 return 0;
1820}
1821
Willy Tarreau92faadf2012-10-10 23:04:25 +02001822/************** "server" keywords ****************/
1823
Emeric Brunef42d922012-10-11 16:11:36 +02001824/* parse the "ca-file" server keyword */
1825static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1826{
1827 if (!*args[*cur_arg + 1]) {
1828 if (err)
1829 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
1830 return ERR_ALERT | ERR_FATAL;
1831 }
1832
1833 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
1834 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
1835 else
1836 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
1837
1838 return 0;
1839}
1840
Willy Tarreau92faadf2012-10-10 23:04:25 +02001841/* parse the "check-ssl" server keyword */
1842static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1843{
1844 newsrv->check.use_ssl = 1;
1845 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
1846 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
1847 return 0;
1848}
1849
1850/* parse the "ciphers" server keyword */
1851static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1852{
1853 if (!*args[*cur_arg + 1]) {
1854 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1855 return ERR_ALERT | ERR_FATAL;
1856 }
1857
1858 free(newsrv->ssl_ctx.ciphers);
1859 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
1860 return 0;
1861}
1862
Emeric Brunef42d922012-10-11 16:11:36 +02001863/* parse the "crl-file" server keyword */
1864static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1865{
1866#ifndef X509_V_FLAG_CRL_CHECK
1867 if (err)
1868 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
1869 return ERR_ALERT | ERR_FATAL;
1870#else
1871 if (!*args[*cur_arg + 1]) {
1872 if (err)
1873 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
1874 return ERR_ALERT | ERR_FATAL;
1875 }
1876
1877 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
1878 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
1879 else
1880 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
1881
1882 return 0;
1883#endif
1884}
1885
1886
Willy Tarreau92faadf2012-10-10 23:04:25 +02001887/* parse the "force-sslv3" server keyword */
1888static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1889{
1890 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
1891 return 0;
1892}
1893
1894/* parse the "force-tlsv10" server keyword */
1895static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1896{
1897 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
1898 return 0;
1899}
1900
1901/* parse the "force-tlsv11" server keyword */
1902static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1903{
1904#if SSL_OP_NO_TLSv1_1
1905 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
1906 return 0;
1907#else
1908 if (err)
1909 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
1910 return ERR_ALERT | ERR_FATAL;
1911#endif
1912}
1913
1914/* parse the "force-tlsv12" server keyword */
1915static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1916{
1917#if SSL_OP_NO_TLSv1_2
1918 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
1919 return 0;
1920#else
1921 if (err)
1922 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
1923 return ERR_ALERT | ERR_FATAL;
1924#endif
1925}
1926
1927/* parse the "no-sslv3" server keyword */
1928static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1929{
1930 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
1931 return 0;
1932}
1933
1934/* parse the "no-tlsv10" server keyword */
1935static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1936{
1937 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
1938 return 0;
1939}
1940
1941/* parse the "no-tlsv11" server keyword */
1942static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1943{
1944 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
1945 return 0;
1946}
1947
1948/* parse the "no-tlsv12" server keyword */
1949static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1950{
1951 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
1952 return 0;
1953}
1954
Emeric Brunf9c5c472012-10-11 15:28:34 +02001955/* parse the "no-tls-tickets" server keyword */
1956static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1957{
1958 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
1959 return 0;
1960}
1961
Willy Tarreau92faadf2012-10-10 23:04:25 +02001962/* parse the "ssl" server keyword */
1963static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1964{
1965 newsrv->use_ssl = 1;
1966 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
1967 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
1968 return 0;
1969}
1970
Emeric Brunef42d922012-10-11 16:11:36 +02001971/* parse the "verify" server keyword */
1972static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1973{
1974 if (!*args[*cur_arg + 1]) {
1975 if (err)
1976 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
1977 return ERR_ALERT | ERR_FATAL;
1978 }
1979
1980 if (strcmp(args[*cur_arg + 1], "none") == 0)
1981 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
1982 else if (strcmp(args[*cur_arg + 1], "required") == 0)
1983 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
1984 else {
1985 if (err)
1986 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
1987 args[*cur_arg], args[*cur_arg + 1]);
1988 return ERR_ALERT | ERR_FATAL;
1989 }
1990
1991 return 0;
1992}
1993
Willy Tarreau7875d092012-09-10 08:20:03 +02001994/* Note: must not be declared <const> as its list will be overwritten.
1995 * Please take care of keeping this list alphabetically sorted.
1996 */
1997static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
Emeric Brun2525b6b2012-10-18 15:59:43 +02001998 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
1999 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2000 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
Willy Tarreau8d598402012-10-22 17:58:39 +02002001 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002002 { "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 +02002003 { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
Willy Tarreau8d598402012-10-22 17:58:39 +02002004 { "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 +02002005 { "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 +02002006 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun589fcad2012-10-16 14:13:26 +02002007 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2008 { "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 +02002009 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
2010 { "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 +02002011#ifdef OPENSSL_NPN_NEGOTIATED
Emeric Brun2525b6b2012-10-18 15:59:43 +02002012 { "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 +02002013#endif
Emeric Brun589fcad2012-10-16 14:13:26 +02002014 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
2015 { "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 +02002016 { "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 +02002017 { "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 +02002018 { NULL, NULL, 0, 0, 0 },
2019}};
2020
2021/* Note: must not be declared <const> as its list will be overwritten.
2022 * Please take care of keeping this list alphabetically sorted.
2023 */
2024static struct acl_kw_list acl_kws = {{ },{
Emeric Brun2525b6b2012-10-18 15:59:43 +02002025 { "ssl_c_ca_err", acl_parse_int, smp_fetch_ssl_c_ca_err, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2026 { "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 },
2027 { "ssl_c_err", acl_parse_int, smp_fetch_ssl_c_err, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Willy Tarreau8d598402012-10-22 17:58:39 +02002028 { "ssl_c_serial", acl_parse_bin, smp_fetch_ssl_c_serial, acl_match_bin, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002029 { "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 +02002030 { "ssl_c_version", acl_parse_int, smp_fetch_ssl_c_version, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Willy Tarreau8d598402012-10-22 17:58:39 +02002031 { "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 +02002032 { "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 +02002033 { "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 +02002034 { "ssl_fc_alg_keysize", acl_parse_str, smp_fetch_ssl_fc_alg_keysize, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2035 { "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 +02002036 { "ssl_fc_has_crt", acl_parse_int, smp_fetch_ssl_fc_has_crt, acl_match_nothing, ACL_USE_L6REQ_PERMANENT, 0 },
2037 { "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 +02002038#ifdef OPENSSL_NPN_NEGOTIATED
Emeric Brun2525b6b2012-10-18 15:59:43 +02002039 { "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 +02002040#endif
Emeric Brun589fcad2012-10-16 14:13:26 +02002041 { "ssl_fc_protocol", acl_parse_str, smp_fetch_ssl_fc_protocol, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2042 { "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 +02002043 { "ssl_fc_sni", acl_parse_str, smp_fetch_ssl_fc_sni, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2044 { "ssl_fc_sni_end", acl_parse_str, smp_fetch_ssl_fc_sni, acl_match_end, ACL_USE_L6REQ_PERMANENT, 0 },
2045 { "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 +02002046 { NULL, NULL, NULL, NULL },
2047}};
2048
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002049/* Note: must not be declared <const> as its list will be overwritten.
2050 * Please take care of keeping this list alphabetically sorted, doing so helps
2051 * all code contributors.
2052 * Optional keywords are also declared with a NULL ->parse() function so that
2053 * the config parser can report an appropriate error when a known keyword was
2054 * not enabled.
2055 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02002056static struct bind_kw_list bind_kws = { "SSL", { }, {
Emeric Brunfb510ea2012-10-05 12:00:26 +02002057 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002058 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
2059 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02002060 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002061 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
2062 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
2063 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002064 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
2065 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
2066 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
2067 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02002068 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
2069 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
2070 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
2071 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002072 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02002073 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
2074 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002075 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002076 { NULL, NULL, 0 },
2077}};
Emeric Brun46591952012-05-18 15:47:34 +02002078
Willy Tarreau92faadf2012-10-10 23:04:25 +02002079/* Note: must not be declared <const> as its list will be overwritten.
2080 * Please take care of keeping this list alphabetically sorted, doing so helps
2081 * all code contributors.
2082 * Optional keywords are also declared with a NULL ->parse() function so that
2083 * the config parser can report an appropriate error when a known keyword was
2084 * not enabled.
2085 */
2086static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02002087 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002088 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
2089 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02002090 { "crl-file", srv_parse_crl_file, 1, 0 }, /* set certificate revocation list file use on server cert verify */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002091 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
2092 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
2093 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
2094 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
2095 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
2096 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
2097 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
2098 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02002099 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02002100 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02002101 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Willy Tarreau92faadf2012-10-10 23:04:25 +02002102 { NULL, NULL, 0, 0 },
2103}};
2104
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002105/* transport-layer operations for SSL sockets */
2106struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02002107 .snd_buf = ssl_sock_from_buf,
2108 .rcv_buf = ssl_sock_to_buf,
2109 .rcv_pipe = NULL,
2110 .snd_pipe = NULL,
2111 .shutr = NULL,
2112 .shutw = ssl_sock_shutw,
2113 .close = ssl_sock_close,
2114 .init = ssl_sock_init,
2115};
2116
2117__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02002118static void __ssl_sock_init(void)
2119{
Emeric Brun46591952012-05-18 15:47:34 +02002120 STACK_OF(SSL_COMP)* cm;
2121
2122 SSL_library_init();
2123 cm = SSL_COMP_get_compression_methods();
2124 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02002125 sample_register_fetches(&sample_fetch_keywords);
2126 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002127 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02002128 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02002129}
2130
2131/*
2132 * Local variables:
2133 * c-indent-level: 8
2134 * c-basic-offset: 8
2135 * End:
2136 */