1 /*
2 * mod_wolfssl - wolfSSL support for lighttpd
3 *
4 * Copyright(c) 2020 Glenn Strauss gstrauss()gluelogic.com All rights reserved
5 * License: BSD 3-clause (same as lighttpd)
6 */
7 /*
8 * Note: If session tickets are -not- disabled with
9 * ssl.openssl.ssl-conf-cmd = ("Options" => "-SessionTicket")
10 * mod_wolfssl rotates server ticket encryption key (STEK) every 8 hours
11 * and keeps the prior two STEKs around, so ticket lifetime is 24 hours.
12 * This is fine for use with a single lighttpd instance, but with multiple
13 * lighttpd workers, no coordinated STEK (server ticket encryption key)
14 * rotation occurs unless ssl.stek-file is defined and maintained (preferred),
15 * or if some external job restarts lighttpd. Restarting lighttpd generates a
16 * new key that is shared by lighttpd workers for the lifetime of the new key.
17 * If the rotation period expires and lighttpd has not been restarted, and if
18 * ssl.stek-file is not in use, then lighttpd workers will generate new
19 * independent keys, making session tickets less effective for session
20 * resumption, since clients have a lower chance for future connections to
21 * reach the same lighttpd worker. However, things will still work, and a new
22 * session will be created if session resumption fails. Admins should plan to
23 * restart lighttpd at least every 8 hours if session tickets are enabled and
24 * multiple lighttpd workers are configured. Since that is likely disruptive,
25 * if multiple lighttpd workers are configured, ssl.stek-file should be
26 * defined and the file maintained externally.
27 */
28 #include "first.h"
29
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <stdint.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 /*
39 * Note: mod_wolfssl.c is forked from mod_openssl.c
40 * Many internal symbol names in mod_wolfssl.c retain the mod_openssl_* prefix
41 * (wolfSSL provides an OpenSSL compatibility layer)
42 */
43
44 /* wolfSSL needs to be built with ./configure --enable-lighty for lighttpd.
45 * Doing so defines OPENSSL_EXTRA and HAVE_LIGHTY in <wolfssl/options.h>, and
46 * these defines are necessary for wolfSSL headers to expose sufficient openssl
47 * compatibility layer for wolfSSL to be able to provide an openssl substitute
48 * for use by lighttpd */
49
50 /* workaround fragile code in wolfssl/wolfcrypto/types.h */
51 #if !defined(SIZEOF_LONG) || !defined(SIZEOF_LONG_LONG)
52 #undef SIZEOF_LONG
53 #undef SIZEOF_LONG_LONG
54 #endif
55
56 #include <wolfssl/options.h>
57 #include <wolfssl/ssl.h>
58 #ifdef HAVE_OCSP
59 #include <wolfssl/ocsp.h>
60 #endif
61
62 static char global_err_buf[WOLFSSL_MAX_ERROR_SZ];
63 #undef ERR_error_string
64 #define ERR_error_string(e,b) \
65 (wolfSSL_ERR_error_string_n((e),global_err_buf,WOLFSSL_MAX_ERROR_SZ), \
66 global_err_buf)
67
68 #if 0 /* symbols and definitions requires WolfSSL built with -DOPENSSL_EXTRA */
69 #define SSL_TLSEXT_ERR_OK 0
70 #define SSL_TLSEXT_ERR_ALERT_FATAL alert_fatal
71 #define SSL_TLSEXT_ERR_NOACK alert_warning
72
73 WOLFSSL_API void wolfSSL_set_verify_depth(WOLFSSL *ssl,int depth);
74
75 WOLFSSL_API void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME* name);
76 WOLFSSL_API int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME* x, const WOLFSSL_X509_NAME* y);
77 WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_NAME_dup(WOLFSSL_X509_NAME*);
78 WOLFSSL_API char* wolfSSL_X509_get_name_oneline(WOLFSSL_X509_NAME*, char*, int);
79
80 WOLFSSL_API const char* wolfSSL_OBJ_nid2sn(int n);
81 WOLFSSL_API int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o);
82 WOLFSSL_API WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne);
83 WOLFSSL_API WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry(WOLFSSL_X509_NAME *name, int loc);
84 #endif
85
86 #if LIBWOLFSSL_VERSION_HEX < 0x04005000
87 #if !defined(OPENSSL_ALL) || LIBWOLFSSL_VERSION_HEX < 0x04002000
88 /*(invalid; but centralize making these calls no-ops)*/
89 #define wolfSSL_sk_X509_NAME_num(a) 0
90 #define wolfSSL_sk_X509_NAME_push(a, b) 0
91 #define wolfSSL_sk_X509_NAME_pop_free(a, b) do { } while (0)
92 #define wolfSSL_sk_X509_NAME_free(a) do { } while (0)
93 #define wolfSSL_X509_get_subject_name(ca) \
94 ((WOLFSSL_X509_NAME *)1) /* ! NULL */
95 #define wolfSSL_sk_X509_NAME_new(a) \
96 ((WOLF_STACK_OF(WOLFSSL_X509_NAME) *)1) /* ! NULL */
97 #endif
98 #endif
99
100 #if LIBWOLFSSL_VERSION_HEX < 0x04006000 || defined(WOLFSSL_NO_FORCE_ZERO)
101 #define wolfSSL_OPENSSL_cleanse(x,sz) ck_memzero((x),(sz))
102 #endif
103
104 #if LIBWOLFSSL_VERSION_HEX < 0x04002000 /*(exact version needed not checked)*/
105 #ifndef STACK_OF
106 #define STACK_OF(x) WOLFSSL_STACK
107 #endif
108 #endif
109
110 #include "base.h"
111 #include "ck.h"
112 #include "fdevent.h"
113 #include "http_header.h"
114 #include "http_kv.h"
115 #include "log.h"
116 #include "plugin.h"
117
118 typedef struct {
119 /* SNI per host: with COMP_SERVER_SOCKET, COMP_HTTP_SCHEME, COMP_HTTP_HOST */
120 buffer *ssl_pemfile_pkey;
121 buffer *ssl_pemfile_x509;
122 buffer **ssl_pemfile_chain;
123 buffer *ssl_stapling;
124 const buffer *ssl_pemfile;
125 const buffer *ssl_privkey;
126 const buffer *ssl_stapling_file;
127 unix_time64_t ssl_stapling_loadts;
128 unix_time64_t ssl_stapling_nextts;
129 char must_staple;
130 } plugin_cert;
131
132 typedef struct {
133 WOLFSSL_CTX *ssl_ctx;
134 } plugin_ssl_ctx;
135
136 typedef struct {
137 STACK_OF(X509_NAME) *names;
138 X509_STORE *certs;
139 } plugin_cacerts;
140
141 typedef struct {
142 WOLFSSL_CTX *ssl_ctx; /* output from network_init_ssl() */
143
144 /*(used only during startup; not patched)*/
145 unsigned char ssl_enabled; /* only interesting for setting up listening sockets. don't use at runtime */
146 unsigned char ssl_honor_cipher_order; /* determine SSL cipher in server-preferred order, not client-order */
147 const buffer *ssl_cipher_list;
148 array *ssl_conf_cmd;
149
150 /*(copied from plugin_data for socket ssl_ctx config)*/
151 const plugin_cert *pc;
152 const plugin_cacerts *ssl_ca_file;
153 STACK_OF(X509_NAME) *ssl_ca_dn_file;
154 const buffer *ssl_ca_crl_file;
155 unsigned char ssl_verifyclient;
156 unsigned char ssl_verifyclient_enforce;
157 unsigned char ssl_verifyclient_depth;
158 unsigned char ssl_read_ahead;
159 } plugin_config_socket; /*(used at startup during configuration)*/
160
161 typedef struct {
162 /* SNI per host: w/ COMP_SERVER_SOCKET, COMP_HTTP_SCHEME, COMP_HTTP_HOST */
163 plugin_cert *pc;
164 const plugin_cacerts *ssl_ca_file;
165 STACK_OF(X509_NAME) *ssl_ca_dn_file;
166 const buffer *ssl_ca_crl_file;
167
168 unsigned char ssl_verifyclient;
169 unsigned char ssl_verifyclient_enforce;
170 unsigned char ssl_verifyclient_depth;
171 unsigned char ssl_verifyclient_export_cert;
172 unsigned char ssl_read_ahead;
173 unsigned char ssl_log_noise;
174 const buffer *ssl_verifyclient_username;
175 const buffer *ssl_acme_tls_1;
176 } plugin_config;
177
178 typedef struct {
179 PLUGIN_DATA;
180 plugin_ssl_ctx *ssl_ctxs;
181 plugin_config defaults;
182 server *srv;
183 array *cafiles;
184 const char *ssl_stek_file;
185 } plugin_data;
186
187 static int ssl_is_init;
188 /* need assigned p->id for deep access of module handler_ctx for connection
189 * i.e. handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id]; */
190 static plugin_data *plugin_data_singleton;
191 #define LOCAL_SEND_BUFSIZE (16 * 1024)
192 static char *local_send_buffer;
193
194 typedef struct {
195 WOLFSSL *ssl;
196 request_st *r;
197 connection *con;
198 short renegotiations; /* count of SSL_CB_HANDSHAKE_START */
199 short close_notify;
200 unsigned short alpn;
201 plugin_config conf;
202 buffer *tmp_buf;
203 log_error_st *errh;
204 } handler_ctx;
205
206
207 static handler_ctx *
handler_ctx_init(void)208 handler_ctx_init (void)
209 {
210 return ck_calloc(1, sizeof(handler_ctx));
211 }
212
213
214 static void
handler_ctx_free(handler_ctx * hctx)215 handler_ctx_free (handler_ctx *hctx)
216 {
217 if (hctx->ssl) SSL_free(hctx->ssl);
218 free(hctx);
219 }
220
221
222 #ifdef HAVE_SESSION_TICKET
223 /* ssl/ssl_local.h */
224 #define TLSEXT_KEYNAME_LENGTH 16
225 #define TLSEXT_TICK_KEY_LENGTH 32
226
227 /* openssl has a huge number of interfaces, but not the most useful;
228 * construct our own session ticket encryption key structure */
229 typedef struct tlsext_ticket_key_st {
230 unix_time64_t active_ts; /* tickets not issued w/ key until activation ts*/
231 unix_time64_t expire_ts; /* key not valid after expiration timestamp */
232 unsigned char tick_key_name[TLSEXT_KEYNAME_LENGTH];
233 unsigned char tick_hmac_key[TLSEXT_TICK_KEY_LENGTH];
234 unsigned char tick_aes_key[TLSEXT_TICK_KEY_LENGTH];
235 } tlsext_ticket_key_t;
236
237 static tlsext_ticket_key_t session_ticket_keys[4];
238 static unix_time64_t stek_rotate_ts;
239
240
241 static int
mod_openssl_session_ticket_key_generate(unix_time64_t active_ts,unix_time64_t expire_ts)242 mod_openssl_session_ticket_key_generate (unix_time64_t active_ts, unix_time64_t expire_ts)
243 {
244 /* openssl RAND_*bytes() functions are called multiple times since the
245 * funcs might have a 32-byte limit on number of bytes returned each call
246 *
247 * (Note: session ticket encryption key generation is not expected to fail)
248 *
249 * 3 keys are stored in session_ticket_keys[]
250 * The 4th element of session_ticket_keys[] is used for STEK construction
251 */
252 /*(RAND_priv_bytes() not in openssl 1.1.0; introduced in openssl 1.1.1)*/
253 #define RAND_priv_bytes(x,sz) RAND_bytes((x),(sz))
254 if (RAND_bytes(session_ticket_keys[3].tick_key_name,
255 TLSEXT_KEYNAME_LENGTH) <= 0
256 || RAND_priv_bytes(session_ticket_keys[3].tick_hmac_key,
257 TLSEXT_TICK_KEY_LENGTH) <= 0
258 || RAND_priv_bytes(session_ticket_keys[3].tick_aes_key,
259 TLSEXT_TICK_KEY_LENGTH) <= 0)
260 return 0;
261 session_ticket_keys[3].active_ts = active_ts;
262 session_ticket_keys[3].expire_ts = expire_ts;
263 return 1;
264 }
265
266
267 static void
mod_openssl_session_ticket_key_rotate(void)268 mod_openssl_session_ticket_key_rotate (void)
269 {
270 /* discard oldest key (session_ticket_keys[2]) and put newest key first
271 * 3 keys are stored in session_ticket_keys[0], [1], [2]
272 * session_ticket_keys[3] is used to construct and pass new STEK */
273
274 session_ticket_keys[2] = session_ticket_keys[1];
275 session_ticket_keys[1] = session_ticket_keys[0];
276 /*memmove(session_ticket_keys+1,
277 session_ticket_keys+0, sizeof(tlsext_ticket_key_t)*2);*/
278 session_ticket_keys[0] = session_ticket_keys[3];
279
280 wolfSSL_OPENSSL_cleanse(session_ticket_keys+3, sizeof(tlsext_ticket_key_t));
281 }
282
283
284 static tlsext_ticket_key_t *
tlsext_ticket_key_get(void)285 tlsext_ticket_key_get (void)
286 {
287 const unix_time64_t cur_ts = log_epoch_secs;
288 const int e = sizeof(session_ticket_keys)/sizeof(*session_ticket_keys) - 1;
289 for (int i = 0; i < e; ++i) {
290 if (session_ticket_keys[i].active_ts > cur_ts) continue;
291 if (session_ticket_keys[i].expire_ts < cur_ts) continue;
292 return &session_ticket_keys[i];
293 }
294 return NULL;
295 }
296
297
298 static tlsext_ticket_key_t *
tlsext_ticket_key_find(unsigned char key_name[16],int * refresh)299 tlsext_ticket_key_find (unsigned char key_name[16], int *refresh)
300 {
301 *refresh = 0;
302 const unix_time64_t cur_ts = log_epoch_secs;
303 const int e = sizeof(session_ticket_keys)/sizeof(*session_ticket_keys) - 1;
304 for (int i = 0; i < e; ++i) {
305 if (session_ticket_keys[i].expire_ts < cur_ts) continue;
306 if (0 == memcmp(session_ticket_keys[i].tick_key_name, key_name, 16))
307 return &session_ticket_keys[i];
308 if (session_ticket_keys[i].active_ts <= cur_ts)
309 *refresh = 1; /* newer active key is available */
310 }
311 return NULL;
312 }
313
314
315 static void
tlsext_ticket_wipe_expired(const unix_time64_t cur_ts)316 tlsext_ticket_wipe_expired (const unix_time64_t cur_ts)
317 {
318 const int e = sizeof(session_ticket_keys)/sizeof(*session_ticket_keys) - 1;
319 for (int i = 0; i < e; ++i) {
320 if (session_ticket_keys[i].expire_ts != 0
321 && session_ticket_keys[i].expire_ts < cur_ts)
322 wolfSSL_OPENSSL_cleanse(session_ticket_keys+i,
323 sizeof(tlsext_ticket_key_t));
324 }
325 }
326
327
328 /* based on reference implementation from openssl 1.1.1g man page
329 * man SSL_CTX_set_tlsext_ticket_key_cb
330 * but openssl code uses EVP_aes_256_cbc() instead of EVP_aes_128_cbc()
331 */
332 #ifndef EVP_MAX_IV_LENGTH
333 #define EVP_MAX_IV_LENGTH 16
334 #endif
335 static int
ssl_tlsext_ticket_key_cb(SSL * s,unsigned char key_name[16],unsigned char iv[EVP_MAX_IV_LENGTH],EVP_CIPHER_CTX * ctx,HMAC_CTX * hctx,int enc)336 ssl_tlsext_ticket_key_cb (SSL *s, unsigned char key_name[16],
337 unsigned char iv[EVP_MAX_IV_LENGTH],
338 EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc)
339 {
340 UNUSED(s);
341 if (enc) { /* create new session */
342 tlsext_ticket_key_t *k = tlsext_ticket_key_get();
343 if (NULL == k)
344 return 0; /* current key does not exist or is not valid */
345 memcpy(key_name, k->tick_key_name, 16);
346 if (RAND_bytes(iv, EVP_MAX_IV_LENGTH) <= 0)
347 return -1; /* insufficient random */
348 EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, k->tick_aes_key, iv);
349 HMAC_Init_ex(hctx, k->tick_hmac_key, sizeof(k->tick_hmac_key),
350 EVP_sha256(), NULL);
351 return 1;
352 }
353 else { /* retrieve session */
354 int refresh;
355 tlsext_ticket_key_t *k = tlsext_ticket_key_find(key_name, &refresh);
356 if (NULL == k)
357 return 0;
358 HMAC_Init_ex(hctx, k->tick_hmac_key, sizeof(k->tick_hmac_key),
359 EVP_sha256(), NULL);
360 EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, k->tick_aes_key, iv);
361 return refresh ? 2 : 1;
362 /* 'refresh' will trigger issuing new ticket for session
363 * even though the current ticket is still valid */
364 }
365 }
366
367
368 static int
mod_openssl_session_ticket_key_file(const char * fn)369 mod_openssl_session_ticket_key_file (const char *fn)
370 {
371 /* session ticket encryption key (STEK)
372 *
373 * STEK file should be stored in non-persistent storage,
374 * e.g. /dev/shm/lighttpd/stek-file (in memory)
375 * with appropriate permissions set to keep stek-file from being
376 * read by other users. Where possible, systems should also be
377 * configured without swap.
378 *
379 * admin should schedule an independent job to periodically
380 * generate new STEK up to 3 times during key lifetime
381 * (lighttpd stores up to 3 keys)
382 *
383 * format of binary file is:
384 * 4-byte - format version (always 0; for use if format changes)
385 * 4-byte - activation timestamp
386 * 4-byte - expiration timestamp
387 * 16-byte - session ticket key name
388 * 32-byte - session ticket HMAC encrpytion key
389 * 32-byte - session ticket AES encrpytion key
390 *
391 * STEK file can be created with a command such as:
392 * dd if=/dev/random bs=1 count=80 status=none | \
393 * perl -e 'print pack("iii",0,time()+300,time()+86400),<>' \
394 * > STEK-file.$$ && mv STEK-file.$$ STEK-file
395 *
396 * The above delays activation time by 5 mins (+300 sec) to allow file to
397 * be propagated to other machines. (admin must handle this independently)
398 * If STEK generation is performed immediately prior to starting lighttpd,
399 * admin should activate keys immediately (without +300).
400 */
401 int buf[23]; /* 92 bytes */
402 int rc = 0; /*(will retry on next check interval upon any error)*/
403 if (0 != fdevent_load_file_bytes((char *)buf,(off_t)sizeof(buf),0,fn,NULL))
404 return rc;
405 if (buf[0] == 0) { /*(format version 0)*/
406 session_ticket_keys[3].active_ts = TIME64_CAST(buf[1]);
407 session_ticket_keys[3].expire_ts = TIME64_CAST(buf[2]);
408 #ifndef __COVERITY__ /* intentional; hide from Coverity Scan */
409 /* intentionally copy 80 bytes into consecutive arrays
410 * tick_key_name[], tick_hmac_key[], tick_aes_key[] */
411 memcpy(&session_ticket_keys[3].tick_key_name, buf+3, 80);
412 #endif
413 rc = 1;
414 }
415
416 wolfSSL_OPENSSL_cleanse(buf, sizeof(buf));
417 return rc;
418 }
419
420
421 static void
mod_openssl_session_ticket_key_check(const plugin_data * p,const unix_time64_t cur_ts)422 mod_openssl_session_ticket_key_check (const plugin_data *p, const unix_time64_t cur_ts)
423 {
424 static unix_time64_t detect_retrograde_ts;
425 if (detect_retrograde_ts > cur_ts && detect_retrograde_ts - cur_ts > 28800)
426 stek_rotate_ts = 0;
427 detect_retrograde_ts = cur_ts;
428
429 int rotate = 0;
430 if (p->ssl_stek_file) {
431 struct stat st;
432 if (0 == stat(p->ssl_stek_file, &st)
433 && TIME64_CAST(st.st_mtime) > stek_rotate_ts)
434 rotate = mod_openssl_session_ticket_key_file(p->ssl_stek_file);
435 tlsext_ticket_wipe_expired(cur_ts);
436 }
437 else if (cur_ts - 28800 >= stek_rotate_ts || 0 == stek_rotate_ts)/*(8 hrs)*/
438 rotate = mod_openssl_session_ticket_key_generate(cur_ts, cur_ts+86400);
439
440 if (rotate) {
441 mod_openssl_session_ticket_key_rotate();
442 stek_rotate_ts = cur_ts;
443 }
444 }
445
446 #endif /* HAVE_SESSION_TICKET */
447
448
449 #ifdef HAVE_OCSP
450 static int
ssl_tlsext_status_cb(SSL * ssl,void * arg)451 ssl_tlsext_status_cb(SSL *ssl, void *arg)
452 {
453 #ifdef SSL_get_tlsext_status_type
454 if (TLSEXT_STATUSTYPE_ocsp != SSL_get_tlsext_status_type(ssl))
455 return SSL_TLSEXT_ERR_NOACK; /* ignore if not client OCSP request */
456 #endif
457
458 handler_ctx *hctx = (handler_ctx *) SSL_get_app_data(ssl);
459 if (NULL == hctx->conf.pc) return SSL_TLSEXT_ERR_NOACK;/*should not happen*/
460 buffer *ssl_stapling = hctx->conf.pc->ssl_stapling;
461 if (NULL == ssl_stapling) return SSL_TLSEXT_ERR_NOACK;
462 UNUSED(arg);
463
464 int len = (int)buffer_clen(ssl_stapling);
465
466 /* wolfSSL caller is going to XFREE() */
467 uint8_t *ocsp_resp = XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
468 if (NULL == ocsp_resp)
469 return SSL_TLSEXT_ERR_NOACK; /* ignore OCSP request if error occurs */
470 memcpy(ocsp_resp, ssl_stapling->ptr, (uint32_t)len);
471
472 if (!SSL_set_tlsext_status_ocsp_resp(ssl, ocsp_resp, len)) {
473 log_error(hctx->r->conf.errh, __FILE__, __LINE__,
474 "SSL: failed to set OCSP response for TLS server name %s: %s",
475 hctx->r->uri.authority.ptr, ERR_error_string(ERR_get_error(), NULL));
476 return SSL_TLSEXT_ERR_NOACK; /* ignore OCSP request if error occurs */
477 /*return SSL_TLSEXT_ERR_ALERT_FATAL;*/
478 }
479 return SSL_TLSEXT_ERR_OK;
480 }
481 #endif
482
483
INIT_FUNC(mod_openssl_init)484 INIT_FUNC(mod_openssl_init)
485 {
486 plugin_data_singleton = (plugin_data *)ck_calloc(1, sizeof(plugin_data));
487 #ifdef DEBUG_WOLFSSL
488 wolfSSL_Debugging_ON();
489 #endif
490 return plugin_data_singleton;
491 }
492
493
mod_openssl_init_once_openssl(server * srv)494 static int mod_openssl_init_once_openssl (server *srv)
495 {
496 if (ssl_is_init) return 1;
497
498 if (wolfSSL_Init() != WOLFSSL_SUCCESS) {
499 log_error(srv->errh, __FILE__, __LINE__,
500 "SSL: wolfSSL_Init() failed");
501 return 0;
502 }
503 ssl_is_init = 1;
504
505 if (0 == RAND_status()) {
506 log_error(srv->errh, __FILE__, __LINE__,
507 "SSL: not enough entropy in the pool");
508 return 0;
509 }
510
511 local_send_buffer = ck_malloc(LOCAL_SEND_BUFSIZE);
512 return 1;
513 }
514
515
mod_openssl_free_openssl(void)516 static void mod_openssl_free_openssl (void)
517 {
518 if (!ssl_is_init) return;
519
520 #ifdef HAVE_SESSION_TICKET
521 wolfSSL_OPENSSL_cleanse(session_ticket_keys, sizeof(session_ticket_keys));
522 stek_rotate_ts = 0;
523 #endif
524
525 if (wolfSSL_Cleanup() != WOLFSSL_SUCCESS) {
526 log_error(plugin_data_singleton->srv->errh, __FILE__, __LINE__,
527 "SSL: wolfSSL_Cleanup() failed");
528 }
529
530 free(local_send_buffer);
531 ssl_is_init = 0;
532 }
533
534
535 static void
mod_wolfssl_free_der_certs(buffer ** certs)536 mod_wolfssl_free_der_certs (buffer **certs)
537 {
538 if (NULL == certs) return;
539 for (int i = 0; NULL != certs[i]; ++i)
540 buffer_free(certs[i]);
541 free(certs);
542 }
543
544
545 static void
mod_openssl_free_config(server * srv,plugin_data * const p)546 mod_openssl_free_config (server *srv, plugin_data * const p)
547 {
548 array_free(p->cafiles);
549
550 if (NULL != p->ssl_ctxs) {
551 SSL_CTX * const ssl_ctx_global_scope = p->ssl_ctxs->ssl_ctx;
552 /* free ssl_ctx from $SERVER["socket"] (if not copy of global scope) */
553 for (uint32_t i = 1; i < srv->config_context->used; ++i) {
554 plugin_ssl_ctx * const s = p->ssl_ctxs + i;
555 if (s->ssl_ctx && s->ssl_ctx != ssl_ctx_global_scope)
556 SSL_CTX_free(s->ssl_ctx);
557 }
558 /* free ssl_ctx from global scope */
559 if (ssl_ctx_global_scope)
560 SSL_CTX_free(ssl_ctx_global_scope);
561 free(p->ssl_ctxs);
562 }
563
564 if (NULL == p->cvlist) return;
565 /* (init i to 0 if global context; to 1 to skip empty global context) */
566 for (int i = !p->cvlist[0].v.u2[1], used = p->nconfig; i < used; ++i) {
567 config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0];
568 for (; -1 != cpv->k_id; ++cpv) {
569 switch (cpv->k_id) {
570 case 0: /* ssl.pemfile */
571 if (cpv->vtype == T_CONFIG_LOCAL) {
572 plugin_cert *pc = cpv->v.v;
573 wolfSSL_OPENSSL_cleanse(pc->ssl_pemfile_pkey->ptr,
574 pc->ssl_pemfile_pkey->size);
575 buffer_free(pc->ssl_pemfile_pkey);
576 /*buffer_free(pc->ssl_pemfile_x509);*//*(part of chain)*/
577 mod_wolfssl_free_der_certs(pc->ssl_pemfile_chain);
578 buffer_free(pc->ssl_stapling);
579 free(pc);
580 }
581 break;
582 case 2: /* ssl.ca-file */
583 if (cpv->vtype == T_CONFIG_LOCAL) {
584 plugin_cacerts *cacerts = cpv->v.v;
585 wolfSSL_sk_X509_NAME_pop_free(cacerts->names,
586 X509_NAME_free);
587 wolfSSL_X509_STORE_free(cacerts->certs);
588 free(cacerts);
589 }
590 break;
591 case 3: /* ssl.ca-dn-file */
592 if (cpv->vtype == T_CONFIG_LOCAL)
593 wolfSSL_sk_X509_NAME_pop_free(cpv->v.v, X509_NAME_free);
594 break;
595 default:
596 break;
597 }
598 }
599 }
600 }
601
602
603 #if LIBWOLFSSL_VERSION_HEX >= 0x04002000
604 static int
mod_wolfssl_cert_is_active(const buffer * b)605 mod_wolfssl_cert_is_active (const buffer *b)
606 {
607 WOLFSSL_X509 *crt =
608 wolfSSL_X509_load_certificate_buffer((const unsigned char *)b->ptr,
609 (int)buffer_clen(b),
610 WOLFSSL_FILETYPE_ASN1);
611 if (NULL == crt) return 0;
612 const WOLFSSL_ASN1_TIME *notBefore = wolfSSL_X509_get_notBefore(crt);
613 const WOLFSSL_ASN1_TIME *notAfter = wolfSSL_X509_get_notAfter(crt);
614 time_t now = (time_t)log_epoch_secs;
615 /*(wolfSSL_X509_cmp_time() might return 0 (WOLFSSL_FAILURE) on failure
616 * to convert WOLFSSL_ASN1_TIME to struct tm; should not happen but WTH?
617 * Also might return -337 (GETTIME_ERROR))*/
618 const int before_cmp = wolfSSL_X509_cmp_time(notBefore, &now);
619 const int after_cmp = wolfSSL_X509_cmp_time(notAfter, &now);
620 wolfSSL_X509_free(crt);
621 return ((before_cmp == -1 || before_cmp == 0) && 0 <= after_cmp);
622 }
623 #endif
624
625
626 /* WolfSSL OpenSSL compat API does not wipe temp mem used; write our own */
627 /* (pemfile might contain private key)*/
628 /* code here is based on similar code in mod_nss */
629 #include "base64.h"
630
631 #define PEM_BEGIN "-----BEGIN "
632 #define PEM_END "-----END "
633 #define PEM_BEGIN_CERT "-----BEGIN CERTIFICATE-----"
634 #define PEM_END_CERT "-----END CERTIFICATE-----"
635 #define PEM_BEGIN_TRUSTED_CERT "-----BEGIN TRUSTED CERTIFICATE-----"
636 #define PEM_END_TRUSTED_CERT "-----END TRUSTED CERTIFICATE-----"
637 #define PEM_BEGIN_PKEY "-----BEGIN PRIVATE KEY-----"
638 #define PEM_END_PKEY "-----END PRIVATE KEY-----"
639 #define PEM_BEGIN_EC_PKEY "-----BEGIN EC PRIVATE KEY-----"
640 #define PEM_END_EC_PKEY "-----END EC PRIVATE KEY-----"
641 #define PEM_BEGIN_RSA_PKEY "-----BEGIN RSA PRIVATE KEY-----"
642 #define PEM_END_RSA_PKEY "-----END RSA PRIVATE KEY-----"
643 #define PEM_BEGIN_DSA_PKEY "-----BEGIN DSA PRIVATE KEY-----"
644 #define PEM_END_DSA_PKEY "-----END DSA PRIVATE KEY-----"
645 #define PEM_BEGIN_ANY_PKEY "-----BEGIN ANY PRIVATE KEY-----"
646 #define PEM_END_ANY_PKEY "-----END ANY PRIVATE KEY-----"
647 /* (not implemented: support to get password from user for encrypted key) */
648 #define PEM_BEGIN_ENCRYPTED_PKEY "-----BEGIN ENCRYPTED PRIVATE KEY-----"
649 #define PEM_END_ENCRYPTED_PKEY "-----END ENCRYPTED PRIVATE KEY-----"
650
651 #define PEM_BEGIN_X509_CRL "-----BEGIN X509 CRL-----"
652 #define PEM_END_X509_CRL "-----END X509 CRL-----"
653
654
655 static buffer *
mod_wolfssl_load_pem_file(const char * fn,log_error_st * errh,buffer *** chain)656 mod_wolfssl_load_pem_file (const char *fn, log_error_st *errh, buffer ***chain)
657 {
658 off_t dlen = 512*1024*1024;/*(arbitrary limit: 512 MB file; expect < 1 MB)*/
659 char *data = fdevent_load_file(fn, &dlen, errh, malloc, free);
660 if (NULL == data) return NULL;
661
662 buffer **certs = NULL;
663 int rc = -1;
664 do {
665 int count = 0;
666 char *b = data;
667 for (; (b = strstr(b, PEM_BEGIN_CERT)); b += sizeof(PEM_BEGIN_CERT)-1)
668 ++count;
669 b = data;
670 for (; (b = strstr(b, PEM_BEGIN_TRUSTED_CERT));
671 b += sizeof(PEM_BEGIN_TRUSTED_CERT)-1)
672 ++count;
673 if (0 == count) {
674 rc = 0;
675 if (NULL == strstr(data, "-----")) {
676 /* does not look like PEM, treat as DER format */
677 certs = ck_malloc(2 * sizeof(buffer *));
678 certs[0] = buffer_init();
679 certs[1] = NULL;
680 buffer_copy_string_len(certs[0], data, dlen);
681 }
682 break;
683 }
684
685 certs = ck_malloc((count+1) * sizeof(buffer *));
686 certs[count] = NULL;
687 for (int i = 0; i < count; ++i)
688 certs[i] = buffer_init();
689
690 buffer *der;
691 int i = 0;
692 for (char *e = data; (b = strstr(e, PEM_BEGIN_CERT)); ++i) {
693 b += sizeof(PEM_BEGIN_CERT)-1;
694 if (*b == '\r') ++b;
695 if (*b == '\n') ++b;
696 e = strstr(b, PEM_END_CERT);
697 if (NULL == e) break;
698 uint32_t len = (uint32_t)(e - b);
699 e += sizeof(PEM_END_CERT)-1;
700 if (i >= count) break; /*(should not happen)*/
701 der = certs[i];
702 if (NULL == buffer_append_base64_decode(der,b,len,BASE64_STANDARD))
703 break;
704 }
705 for (char *e = data; (b = strstr(e, PEM_BEGIN_TRUSTED_CERT)); ++i) {
706 b += sizeof(PEM_BEGIN_TRUSTED_CERT)-1;
707 if (*b == '\r') ++b;
708 if (*b == '\n') ++b;
709 e = strstr(b, PEM_END_TRUSTED_CERT);
710 if (NULL == e) break;
711 uint32_t len = (uint32_t)(e - b);
712 e += sizeof(PEM_END_TRUSTED_CERT)-1;
713 if (i >= count) break; /*(should not happen)*/
714 der = certs[i];
715 if (NULL == buffer_append_base64_decode(der,b,len,BASE64_STANDARD))
716 break;
717 }
718 if (i == count)
719 rc = 0;
720 else
721 errno = EIO;
722 } while (0);
723
724 if (dlen) ck_memzero(data, dlen);
725 free(data);
726
727 if (rc < 0) {
728 log_perror(errh, __FILE__, __LINE__, "error loading %s", fn);
729 mod_wolfssl_free_der_certs(certs);
730 certs = NULL;
731 }
732
733 #if LIBWOLFSSL_VERSION_HEX >= 0x04002000
734 if (certs && !mod_wolfssl_cert_is_active(certs[0]))
735 log_error(errh, __FILE__, __LINE__,
736 "SSL: inactive/expired X509 certificate '%s'", fn);
737 #endif
738
739 *chain = certs;
740 return certs ? certs[0] : NULL;
741 }
742
743
744 static buffer *
mod_wolfssl_evp_pkey_load_pem_file(const char * fn,log_error_st * errh)745 mod_wolfssl_evp_pkey_load_pem_file (const char *fn, log_error_st *errh)
746 {
747 off_t dlen = 512*1024*1024;/*(arbitrary limit: 512 MB file; expect < 1 MB)*/
748 char *data = fdevent_load_file(fn, &dlen, errh, malloc, free);
749 if (NULL == data) return NULL;
750
751 buffer *pkey = NULL;
752 int rc = -1;
753 do {
754 /*(expecting single private key in file, so first match)*/
755 char *b, *e;
756 if ((b = strstr(data, PEM_BEGIN_PKEY))
757 && (e = strstr(b, PEM_END_PKEY)))
758 b += sizeof(PEM_BEGIN_PKEY)-1;
759 else if ((b = strstr(data, PEM_BEGIN_EC_PKEY))
760 && (e = strstr(b, PEM_END_EC_PKEY)))
761 b += sizeof(PEM_BEGIN_EC_PKEY)-1;
762 else if ((b = strstr(data, PEM_BEGIN_RSA_PKEY))
763 && (e = strstr(b, PEM_END_RSA_PKEY)))
764 b += sizeof(PEM_BEGIN_RSA_PKEY)-1;
765 else if ((b = strstr(data, PEM_BEGIN_DSA_PKEY))
766 && (e = strstr(b, PEM_END_DSA_PKEY)))
767 b += sizeof(PEM_BEGIN_DSA_PKEY)-1;
768 else if ((b = strstr(data, PEM_BEGIN_ANY_PKEY))
769 && (e = strstr(b, PEM_END_ANY_PKEY)))
770 b += sizeof(PEM_BEGIN_ANY_PKEY)-1;
771 else if (NULL == strstr(data, "-----")) {
772 /* does not look like PEM, treat as DER format */
773 pkey = buffer_init();
774 buffer_copy_string_len(pkey, data, dlen);
775 rc = 0;
776 break;
777 }
778 else
779 break;
780 if (*b == '\r') ++b;
781 if (*b == '\n') ++b;
782
783 pkey = buffer_init();
784 size_t len = (size_t)(e - b);
785 if (NULL == buffer_append_base64_decode(pkey, b, len, BASE64_STANDARD))
786 break;
787 rc = 0;
788 } while (0);
789
790 if (dlen) ck_memzero(data, dlen);
791 free(data);
792
793 if (rc < 0) {
794 log_error(errh, __FILE__, __LINE__, "%s() %s", __func__, fn);
795 if (pkey) {
796 wolfSSL_OPENSSL_cleanse(pkey->ptr, pkey->size);
797 buffer_free(pkey);
798 }
799 return NULL;
800 }
801
802 return pkey;
803 }
804
805
806 static int
mod_wolfssl_CTX_use_certificate_chain_file(WOLFSSL_CTX * ssl_ctx,const char * fn,log_error_st * errh)807 mod_wolfssl_CTX_use_certificate_chain_file (WOLFSSL_CTX *ssl_ctx, const char *fn, log_error_st *errh)
808 {
809 /* (While it should be possible to parse DERs from (buffer **)
810 * s->pc->ssl_pemfile_chain, it is simpler to re-read file and use the
811 * built-in wolfSSL_CTX_use_certificate_chain_buffer() interface) */
812 off_t dlen = 4*1024*1024;/*(arbitrary limit: 4 MB file; expect < 1 KB)*/
813 char *data = fdevent_load_file(fn, &dlen, errh, malloc, free);
814 if (NULL == data) return -1;
815
816 int rc = (NULL != strstr(data, "-----"))
817 ? wolfSSL_CTX_use_certificate_chain_buffer(ssl_ctx, (unsigned char *)data,
818 (long)dlen)
819 : wolfSSL_CTX_use_certificate_chain_buffer_format(ssl_ctx,
820 (unsigned char *)data,
821 (long)dlen,
822 WOLFSSL_FILETYPE_ASN1);
823
824 if (dlen) ck_memzero(data, dlen);
825 free(data);
826
827 if (rc == WOLFSSL_SUCCESS)
828 return 1;
829
830 log_error(errh, __FILE__, __LINE__,
831 "SSL: %s %s", ERR_error_string(rc, NULL), fn);
832 return 0;
833 }
834
835
STACK_OF(X509_NAME)836 static STACK_OF(X509_NAME) *
837 mod_wolfssl_load_client_CA_file (const buffer *ssl_ca_file, log_error_st *errh)
838 {
839 /* similar to wolfSSL_load_client_CA_file(), plus some processing */
840 buffer **certs = NULL;
841 if (NULL == mod_wolfssl_load_pem_file(ssl_ca_file->ptr, errh, &certs)) {
842 #if defined(__clang_analyzer__) || defined(__COVERITY__)
843 mod_wolfssl_free_der_certs(certs); /*unnecessary; quiet clang analyzer*/
844 #endif
845 return NULL;
846 }
847
848 WOLF_STACK_OF(WOLFSSL_X509_NAME) *canames = wolfSSL_sk_X509_NAME_new(NULL);
849 if (NULL == canames) {
850 mod_wolfssl_free_der_certs(certs);
851 return NULL;
852 }
853
854 /* wolfSSL_sk_X509_NAME_push prior to version 4.8.0 returned 0 on success.
855 * The return value was changed to WOLFSSL_SUCCESS (not 0) from 4.8.0. */
856 const int x = wolfSSL_lib_version_hex() < 0x04008000 ? 0 : WOLFSSL_SUCCESS;
857 for (int i = 0; NULL != certs[i]; ++i) {
858 WOLFSSL_X509 *ca =
859 wolfSSL_X509_load_certificate_buffer((unsigned char *)certs[i]->ptr,
860 (int)buffer_clen(certs[i]),
861 WOLFSSL_FILETYPE_ASN1);
862 WOLFSSL_X509_NAME *subj = NULL;
863 if (NULL == ca
864 || NULL == (subj = wolfSSL_X509_get_subject_name(ca))
865 || x != wolfSSL_sk_X509_NAME_push(canames,
866 wolfSSL_X509_NAME_dup(subj))) {
867 log_error(errh, __FILE__, __LINE__,
868 "SSL: couldn't read X509 certificates from '%s'",
869 ssl_ca_file->ptr);
870 if (subj) wolfSSL_X509_NAME_free(subj);
871 if (ca) wolfSSL_X509_free(ca);
872 wolfSSL_sk_X509_NAME_free(canames);
873 mod_wolfssl_free_der_certs(certs);
874 return NULL;
875 }
876
877 wolfSSL_X509_free(ca);
878 }
879
880 mod_wolfssl_free_der_certs(certs);
881 return canames;
882 }
883
884
885 static plugin_cacerts *
mod_wolfssl_load_cacerts(const buffer * ssl_ca_file,log_error_st * errh)886 mod_wolfssl_load_cacerts (const buffer *ssl_ca_file, log_error_st *errh)
887 {
888 /* similar to mod_wolfSSL_load_client_CA_file(), plus some processing */
889 /* similar to wolfSSL_load_client_CA_file(), plus some processing */
890 buffer **certs = NULL;
891 if (NULL == mod_wolfssl_load_pem_file(ssl_ca_file->ptr, errh, &certs)) {
892 #if defined(__clang_analyzer__) || defined(__COVERITY__)
893 mod_wolfssl_free_der_certs(certs); /*unnecessary; quiet clang analyzer*/
894 #endif
895 return NULL;
896 }
897
898 WOLFSSL_X509_STORE *castore = wolfSSL_X509_STORE_new();
899 if (NULL == castore) {
900 mod_wolfssl_free_der_certs(certs);
901 return NULL;
902 }
903
904 WOLF_STACK_OF(WOLFSSL_X509_NAME) *canames = wolfSSL_sk_X509_NAME_new(NULL);
905 if (NULL == canames) {
906 wolfSSL_X509_STORE_free(castore);
907 mod_wolfssl_free_der_certs(certs);
908 return NULL;
909 }
910
911 /* wolfSSL_sk_X509_NAME_push prior to version 4.8.0 returned 0 on success.
912 * The return value was changed to WOLFSSL_SUCCESS (not 0) from 4.8.0. */
913 const int x = wolfSSL_lib_version_hex() < 0x04008000 ? 0 : WOLFSSL_SUCCESS;
914 for (int i = 0; NULL != certs[i]; ++i) {
915 WOLFSSL_X509 *ca =
916 wolfSSL_X509_load_certificate_buffer((unsigned char *)certs[i]->ptr,
917 (int)buffer_clen(certs[i]),
918 WOLFSSL_FILETYPE_ASN1);
919 WOLFSSL_X509_NAME *subj = NULL;
920 if (NULL == ca || !wolfSSL_X509_STORE_add_cert(castore, ca)
921 || NULL == (subj = wolfSSL_X509_get_subject_name(ca))
922 || x != wolfSSL_sk_X509_NAME_push(canames,
923 wolfSSL_X509_NAME_dup(subj))) {
924 log_error(errh, __FILE__, __LINE__,
925 "SSL: couldn't read X509 certificates from '%s'",
926 ssl_ca_file->ptr);
927 if (subj) wolfSSL_X509_NAME_free(subj);
928 if (ca) wolfSSL_X509_free(ca);
929 wolfSSL_sk_X509_NAME_free(canames);
930 wolfSSL_X509_STORE_free(castore);
931 mod_wolfssl_free_der_certs(certs);
932 return NULL;
933 }
934
935 wolfSSL_X509_free(ca);
936 }
937
938 mod_wolfssl_free_der_certs(certs);
939
940 plugin_cacerts *cacerts = ck_malloc(sizeof(plugin_cacerts));
941 cacerts->names = canames;
942 cacerts->certs = castore;
943 return cacerts;
944 }
945
946
947 static int
mod_wolfssl_load_cacrls(WOLFSSL_CTX * ssl_ctx,const buffer * ssl_ca_crl_file,server * srv)948 mod_wolfssl_load_cacrls (WOLFSSL_CTX *ssl_ctx, const buffer *ssl_ca_crl_file, server *srv)
949 {
950 #ifdef HAVE_CRL /* <wolfssl/options.h> */
951 int rc = wolfSSL_CTX_EnableCRL(ssl_ctx,
952 WOLFSSL_CRL_CHECK | WOLFSSL_CRL_CHECKALL);
953 if (rc != WOLFSSL_SUCCESS) return 0;
954
955 const char *fn = ssl_ca_crl_file->ptr;
956 off_t dlen = 512*1024*1024;/*(arbitrary limit: 512 MB file; expect < 1 MB)*/
957 char *data = fdevent_load_file(fn, &dlen, srv->errh, malloc, free);
958 if (NULL == data) return 0;
959
960 rc = wolfSSL_CTX_LoadCRLBuffer(ssl_ctx, (byte *)data, (long)dlen,
961 WOLFSSL_FILETYPE_PEM);
962
963 if (dlen) ck_memzero(data, dlen);
964 free(data);
965
966 if (rc == WOLFSSL_SUCCESS)
967 return 1;
968
969 log_error(srv->errh, __FILE__, __LINE__,
970 "SSL: %s %s", ERR_error_string(rc, NULL), fn);
971 return 0;
972 #else
973 UNUSED(ssl_ctx);
974 log_error(srv->errh, __FILE__, __LINE__,
975 "WolfSSL not built with CRL support; ignoring %s", ssl_ca_crl_file->ptr);
976 return WOLFSSL_FAILURE;
977 #endif
978 }
979
980
981 static int
mod_wolfssl_load_verify_locn(SSL_CTX * ssl_ctx,const buffer * b,server * srv)982 mod_wolfssl_load_verify_locn (SSL_CTX *ssl_ctx, const buffer *b, server *srv)
983 {
984 const char *fn = b->ptr;
985 off_t dlen = 512*1024*1024;/*(arbitrary limit: 512 MB file; expect < 1 MB)*/
986 char *data = fdevent_load_file(fn, &dlen, srv->errh, malloc, free);
987 if (NULL == data) return 0;
988
989 int rc = wolfSSL_CTX_load_verify_buffer(ssl_ctx, (unsigned char *)data,
990 (long)dlen, WOLFSSL_FILETYPE_PEM);
991
992 if (dlen) ck_memzero(data, dlen);
993 free(data);
994
995 if (rc == WOLFSSL_SUCCESS)
996 return 1;
997
998 log_error(srv->errh, __FILE__, __LINE__,
999 "SSL: %s %s", ERR_error_string(rc, NULL), fn);
1000 return 0;
1001 }
1002
1003
1004 static int
mod_wolfssl_load_ca_files(SSL_CTX * ssl_ctx,plugin_data * p,server * srv)1005 mod_wolfssl_load_ca_files (SSL_CTX *ssl_ctx, plugin_data *p, server *srv)
1006 {
1007 /* load all ssl.ca-files specified in the config into each SSL_CTX */
1008
1009 for (uint32_t i = 0, used = p->cafiles->used; i < used; ++i) {
1010 const buffer *b = &((data_string *)p->cafiles->data[i])->value;
1011 if (!mod_wolfssl_load_verify_locn(ssl_ctx, b, srv))
1012 return 0;
1013 }
1014 return 1;
1015 }
1016
1017
FREE_FUNC(mod_openssl_free)1018 FREE_FUNC(mod_openssl_free)
1019 {
1020 plugin_data *p = p_d;
1021 if (NULL == p->srv) return;
1022 mod_openssl_free_config(p->srv, p);
1023 mod_openssl_free_openssl();
1024 }
1025
1026
1027 static void
mod_openssl_merge_config_cpv(plugin_config * const pconf,const config_plugin_value_t * const cpv)1028 mod_openssl_merge_config_cpv (plugin_config * const pconf, const config_plugin_value_t * const cpv)
1029 {
1030 switch (cpv->k_id) { /* index into static config_plugin_keys_t cpk[] */
1031 case 0: /* ssl.pemfile */
1032 if (cpv->vtype == T_CONFIG_LOCAL)
1033 pconf->pc = cpv->v.v;
1034 break;
1035 case 1: /* ssl.privkey */
1036 break;
1037 case 2: /* ssl.ca-file */
1038 if (cpv->vtype == T_CONFIG_LOCAL)
1039 pconf->ssl_ca_file = cpv->v.v;
1040 break;
1041 case 3: /* ssl.ca-dn-file */
1042 if (cpv->vtype == T_CONFIG_LOCAL)
1043 pconf->ssl_ca_dn_file = cpv->v.v;
1044 break;
1045 case 4: /* ssl.ca-crl-file */
1046 pconf->ssl_ca_crl_file = cpv->v.b;
1047 break;
1048 case 5: /* ssl.read-ahead */
1049 pconf->ssl_read_ahead = (0 != cpv->v.u);
1050 break;
1051 case 6: /* ssl.disable-client-renegotiation */
1052 /*(ignored; unsafe renegotiation disabled by default)*/
1053 break;
1054 case 7: /* ssl.verifyclient.activate */
1055 pconf->ssl_verifyclient = (0 != cpv->v.u);
1056 break;
1057 case 8: /* ssl.verifyclient.enforce */
1058 pconf->ssl_verifyclient_enforce = (0 != cpv->v.u);
1059 break;
1060 case 9: /* ssl.verifyclient.depth */
1061 pconf->ssl_verifyclient_depth = (unsigned char)cpv->v.shrt;
1062 break;
1063 case 10:/* ssl.verifyclient.username */
1064 pconf->ssl_verifyclient_username = cpv->v.b;
1065 break;
1066 case 11:/* ssl.verifyclient.exportcert */
1067 pconf->ssl_verifyclient_export_cert = (0 != cpv->v.u);
1068 break;
1069 case 12:/* ssl.acme-tls-1 */
1070 pconf->ssl_acme_tls_1 = cpv->v.b;
1071 break;
1072 case 13:/* ssl.stapling-file */
1073 break;
1074 case 14:/* debug.log-ssl-noise */
1075 pconf->ssl_log_noise = (0 != cpv->v.u);
1076 break;
1077 #if 0 /*(cpk->k_id remapped in mod_openssl_set_defaults())*/
1078 case 15:/* ssl.verifyclient.ca-file */
1079 case 16:/* ssl.verifyclient.ca-dn-file */
1080 case 17:/* ssl.verifyclient.ca-crl-file */
1081 break;
1082 #endif
1083 default:/* should not happen */
1084 return;
1085 }
1086 }
1087
1088
1089 static void
mod_openssl_merge_config(plugin_config * const pconf,const config_plugin_value_t * cpv)1090 mod_openssl_merge_config(plugin_config * const pconf, const config_plugin_value_t *cpv)
1091 {
1092 do {
1093 mod_openssl_merge_config_cpv(pconf, cpv);
1094 } while ((++cpv)->k_id != -1);
1095 }
1096
1097
1098 static void
mod_openssl_patch_config(request_st * const r,plugin_config * const pconf)1099 mod_openssl_patch_config (request_st * const r, plugin_config * const pconf)
1100 {
1101 plugin_data * const p = plugin_data_singleton;
1102 memcpy(pconf, &p->defaults, sizeof(plugin_config));
1103 for (int i = 1, used = p->nconfig; i < used; ++i) {
1104 if (config_check_cond(r, (uint32_t)p->cvlist[i].k_id))
1105 mod_openssl_merge_config(pconf, p->cvlist + p->cvlist[i].v.u2[0]);
1106 }
1107 }
1108
1109
1110 static int
safer_X509_NAME_oneline(X509_NAME * name,char * buf,size_t sz)1111 safer_X509_NAME_oneline(X509_NAME *name, char *buf, size_t sz)
1112 {
1113 #if LIBWOLFSSL_VERSION_HEX < 0x04004000
1114 UNUSED(name);
1115 UNUSED(sz);
1116 #else
1117 if (wolfSSL_X509_get_name_oneline(name, buf, (int)sz))
1118 return (int)strlen(buf);
1119 else
1120 #endif
1121 {
1122 buf[0] = '\0';
1123 return -1;
1124 }
1125 }
1126
1127
1128 static void
ssl_info_callback(const SSL * ssl,int where,int ret)1129 ssl_info_callback (const SSL *ssl, int where, int ret)
1130 {
1131 UNUSED(ret);
1132
1133 if (0 != (where & SSL_CB_HANDSHAKE_START)) {
1134 handler_ctx *hctx = (handler_ctx *) SSL_get_app_data(ssl);
1135 if (hctx->renegotiations >= 0) ++hctx->renegotiations;
1136 }
1137 /* https://github.com/openssl/openssl/issues/5721
1138 * "TLSv1.3 unexpected InfoCallback after handshake completed" */
1139 if (0 != (where & SSL_CB_HANDSHAKE_DONE)) {
1140 /* SSL_version() is valid after initial handshake completed */
1141 SSL *ssl_nonconst;
1142 *(const SSL **)&ssl_nonconst = ssl;
1143 if (wolfSSL_GetVersion(ssl_nonconst) >= WOLFSSL_TLSV1_3) {
1144 /* https://wiki.openssl.org/index.php/TLS1.3
1145 * "Renegotiation is not possible in a TLSv1.3 connection" */
1146 handler_ctx *hctx = (handler_ctx *) SSL_get_app_data(ssl);
1147 hctx->renegotiations = -1;
1148 }
1149 }
1150 }
1151
1152 /* https://wiki.openssl.org/index.php/Manual:SSL_CTX_set_verify(3)#EXAMPLES */
1153 static int
verify_callback(int preverify_ok,X509_STORE_CTX * ctx)1154 verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
1155 {
1156 char buf[256];
1157 X509 *err_cert;
1158 int err, depth;
1159 SSL *ssl;
1160 handler_ctx *hctx;
1161
1162 err = X509_STORE_CTX_get_error(ctx);
1163 depth = X509_STORE_CTX_get_error_depth(ctx);
1164
1165 /*
1166 * Retrieve the pointer to the SSL of the connection currently treated
1167 * and the application specific data stored into the SSL object.
1168 */
1169 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
1170 hctx = (handler_ctx *) SSL_get_app_data(ssl);
1171
1172 /*
1173 * Catch a too long certificate chain. The depth limit set using
1174 * wolfSSL_CTX_set_verify_depth() is by purpose set to "limit+1" so
1175 * that whenever the "depth>verify_depth" condition is met, we
1176 * have violated the limit and want to log this error condition.
1177 * We must do it here, because the CHAIN_TOO_LONG error would not
1178 * be found explicitly; only errors introduced by cutting off the
1179 * additional certificates would be logged.
1180 */
1181 if (depth > hctx->conf.ssl_verifyclient_depth) {
1182 preverify_ok = 0;
1183 err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
1184 X509_STORE_CTX_set_error(ctx, err);
1185 }
1186
1187 if (preverify_ok && 0 == depth && NULL != hctx->conf.ssl_ca_dn_file) {
1188 /* verify that client cert is issued by CA in ssl.ca-dn-file
1189 * if both ssl.ca-dn-file and ssl.ca-file were configured */
1190 STACK_OF(X509_NAME) * const cert_names = hctx->conf.ssl_ca_dn_file;
1191 X509_NAME *issuer;
1192 err_cert = ctx->current_cert;/*wolfSSL_X509_STORE_CTX_get_current_cert*/
1193 if (NULL == err_cert) return !hctx->conf.ssl_verifyclient_enforce;
1194 issuer = X509_get_issuer_name(err_cert);
1195 #if 0 /*(?desirable/undesirable to have cert_names sorted?)*/
1196 if (-1 != sk_X509_NAME_find(cert_names, issuer))
1197 return preverify_ok; /* match */
1198 #else
1199 for (int i=0, len=wolfSSL_sk_X509_NAME_num(cert_names); i < len; ++i) {
1200 if (0 == wolfSSL_X509_NAME_cmp(sk_X509_NAME_value(cert_names, i),
1201 issuer))
1202 return preverify_ok; /* match */
1203 }
1204 #endif
1205
1206 preverify_ok = 0;
1207 err = X509_V_ERR_CERT_REJECTED;
1208 X509_STORE_CTX_set_error(ctx, err);
1209 }
1210
1211 if (preverify_ok) {
1212 return preverify_ok;
1213 }
1214
1215 err_cert = ctx->current_cert; /*wolfSSL_X509_STORE_CTX_get_current_cert()*/
1216 if (NULL == err_cert) return !hctx->conf.ssl_verifyclient_enforce;
1217 safer_X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof(buf));
1218 log_error_st *errh = hctx->r->conf.errh;
1219 log_error(errh, __FILE__, __LINE__,
1220 "SSL: verify error:num=%d:%s:depth=%d:subject=%s",
1221 err, X509_verify_cert_error_string(err), depth, buf);
1222
1223 /*
1224 * At this point, err contains the last verification error. We can use
1225 * it for something special
1226 */
1227 if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY ||
1228 err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)) {
1229 safer_X509_NAME_oneline(X509_get_issuer_name(err_cert),buf,sizeof(buf));
1230 log_error(errh, __FILE__, __LINE__, "SSL: issuer=%s", buf);
1231 }
1232
1233 return !hctx->conf.ssl_verifyclient_enforce;
1234 }
1235
1236 static int
mod_openssl_cert_cb(SSL * ssl,void * arg)1237 mod_openssl_cert_cb (SSL *ssl, void *arg)
1238 {
1239 handler_ctx *hctx = (handler_ctx *) SSL_get_app_data(ssl);
1240 plugin_cert *pc = hctx->conf.pc;
1241 UNUSED(arg);
1242
1243 if (!pc || NULL == pc->ssl_pemfile_x509 || NULL == pc->ssl_pemfile_pkey) {
1244 /* x509/pkey available <=> pemfile was set <=> pemfile got patched:
1245 * so this should never happen, unless you nest $SERVER["socket"] */
1246 log_error(hctx->r->conf.errh, __FILE__, __LINE__,
1247 "SSL: no certificate/private key for TLS server name \"%s\". "
1248 "$SERVER[\"socket\"] should not be nested in other conditions.",
1249 hctx->r->uri.authority.ptr);
1250 return 0;
1251 }
1252
1253 /* first set certificate!
1254 * setting private key checks whether certificate matches it */
1255 buffer *cert = pc->ssl_pemfile_x509;
1256 if (1 != wolfSSL_use_certificate_ASN1(ssl, (unsigned char *)cert->ptr,
1257 (int)buffer_clen(cert))) {
1258 log_error(hctx->r->conf.errh, __FILE__, __LINE__,
1259 "SSL: failed to set certificate for TLS server name %s: %s",
1260 hctx->r->uri.authority.ptr, ERR_error_string(ERR_get_error(), NULL));
1261 return 0;
1262 }
1263
1264 buffer *pkey = pc->ssl_pemfile_pkey;
1265 if (1 != wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char *)pkey->ptr,
1266 (int)buffer_clen(pkey),
1267 WOLFSSL_FILETYPE_ASN1)) {
1268 log_error(hctx->r->conf.errh, __FILE__, __LINE__,
1269 "SSL: failed to set private key for TLS server name %s: %s",
1270 hctx->r->uri.authority.ptr, ERR_error_string(ERR_get_error(), NULL));
1271 return 0;
1272 }
1273
1274 if (hctx->conf.ssl_verifyclient) {
1275 if (NULL == hctx->conf.ssl_ca_file) {
1276 log_error(hctx->r->conf.errh, __FILE__, __LINE__,
1277 "SSL: can't verify client without ssl.verifyclient.ca-file "
1278 "for TLS server name %s", hctx->r->uri.authority.ptr);
1279 return 0;
1280 }
1281 /* WolfSSL does not support setting per-session CA list;
1282 * limitation is to per-CTX CA list, and is not changed after SNI */
1283 int mode = SSL_VERIFY_PEER;
1284 if (hctx->conf.ssl_verifyclient_enforce)
1285 mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
1286 wolfSSL_set_verify(ssl, mode, verify_callback);
1287 wolfSSL_set_verify_depth(ssl, hctx->conf.ssl_verifyclient_depth + 1);
1288 }
1289 else {
1290 wolfSSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
1291 }
1292
1293 return 1;
1294 }
1295
1296 #ifdef HAVE_TLS_EXTENSIONS
1297
1298 enum {
1299 MOD_OPENSSL_ALPN_HTTP11 = 1
1300 ,MOD_OPENSSL_ALPN_HTTP10 = 2
1301 ,MOD_OPENSSL_ALPN_H2 = 3
1302 ,MOD_OPENSSL_ALPN_ACME_TLS_1 = 4
1303 };
1304
1305 static int
mod_openssl_SNI(handler_ctx * hctx,const char * servername,size_t len)1306 mod_openssl_SNI (handler_ctx *hctx, const char *servername, size_t len)
1307 {
1308 request_st * const r = hctx->r;
1309 if (len >= 1024) { /*(expecting < 256; TLSEXT_MAXLEN_host_name is 255)*/
1310 log_error(r->conf.errh, __FILE__, __LINE__,
1311 "SSL: SNI name too long %.*s", (int)len, servername);
1312 return SSL_TLSEXT_ERR_ALERT_FATAL;
1313 }
1314
1315 /* use SNI to patch mod_openssl config and then reset COMP_HTTP_HOST */
1316 buffer_copy_string_len_lc(&r->uri.authority, servername, len);
1317 #if 0
1318 /*(r->uri.authority used below for configuration before request read;
1319 * revisit for h2)*/
1320 if (0 != http_request_host_policy(&r->uri.authority,
1321 r->conf.http_parseopts, 443))
1322 return SSL_TLSEXT_ERR_ALERT_FATAL;
1323 #endif
1324
1325 r->conditional_is_valid |= (1 << COMP_HTTP_SCHEME)
1326 | (1 << COMP_HTTP_HOST);
1327 mod_openssl_patch_config(r, &hctx->conf);
1328 /* reset COMP_HTTP_HOST so that conditions re-run after request hdrs read */
1329 /*(done in response.c:config_cond_cache_reset() after request hdrs read)*/
1330 /*config_cond_cache_reset_item(r, COMP_HTTP_HOST);*/
1331 /*buffer_clear(&r->uri.authority);*/
1332
1333 return (mod_openssl_cert_cb(hctx->ssl, NULL) == 1)
1334 ? SSL_TLSEXT_ERR_OK
1335 : SSL_TLSEXT_ERR_ALERT_FATAL;
1336 }
1337
1338 static int
network_ssl_servername_callback(SSL * ssl,int * al,void * srv)1339 network_ssl_servername_callback (SSL *ssl, int *al, void *srv)
1340 {
1341 handler_ctx *hctx = (handler_ctx *) SSL_get_app_data(ssl);
1342 #ifdef HAVE_ALPN
1343 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1344 /*(do not repeat if acme-tls/1 creds have been set
1345 * and still in handshake (hctx->alpn not unset yet))*/
1346 if (hctx->alpn == MOD_OPENSSL_ALPN_ACME_TLS_1)
1347 return SSL_TLSEXT_ERR_OK; /*(wolfSSL might call twice in client hello)*/
1348 #endif
1349 #endif
1350 if (hctx->r->conditional_is_valid & (1 << COMP_HTTP_HOST))/*(already done)*/
1351 return SSL_TLSEXT_ERR_OK; /*(wolfSSL might call twice in client hello)*/
1352 buffer_copy_string_len(&hctx->r->uri.scheme, CONST_STR_LEN("https"));
1353 UNUSED(al);
1354 UNUSED(srv);
1355
1356 const char *servername;
1357 size_t len = (size_t)
1358 #ifdef HAVE_SNI
1359 wolfSSL_SNI_GetRequest(ssl, WOLFSSL_SNI_HOST_NAME, (void **)&servername);
1360 #else
1361 0;
1362 #endif
1363 if (0 == len)
1364 return SSL_TLSEXT_ERR_NOACK; /* client did not provide SNI */
1365 #if 0 /* WolfSSL does not provide per-session SSL_set_read_ahead() */
1366 int read_ahead = hctx->conf.ssl_read_ahead;
1367 int rc = mod_openssl_SNI(hctx, servername, len);
1368 if (!read_ahead && hctx->conf.ssl_read_ahead)
1369 SSL_set_read_ahead(ssl, hctx->conf.ssl_read_ahead);
1370 return rc;
1371 #else
1372 return mod_openssl_SNI(hctx, servername, len);
1373 #endif
1374 }
1375
1376 #endif /* HAVE_TLS_EXTENSIONS */
1377
1378
1379 #ifdef HAVE_OCSP
1380
1381 #define OCSP_RESPONSE OcspResponse
1382 #define OCSP_RESPONSE_free wolfSSL_OCSP_RESPONSE_free
1383 #define d2i_OCSP_RESPONSE_bio wolfSSL_d2i_OCSP_RESPONSE_bio
1384 #define d2i_OCSP_RESPONSE wolfSSL_d2i_OCSP_RESPONSE
1385 #define i2d_OCSP_RESPONSE wolfSSL_i2d_OCSP_RESPONSE
1386 #define OCSP_response_get1_basic wolfSSL_OCSP_response_get1_basic
1387 #define OCSP_single_get0_status wolfSSL_OCSP_single_get0_status
1388 #define OCSP_resp_get0 wolfSSL_OCSP_resp_get0
1389 #define OCSP_BASICRESP WOLFSSL_OCSP_BASICRESP
1390 #define OCSP_BASICRESP_free wolfSSL_OCSP_BASICRESP_free
1391
1392 static buffer *
mod_openssl_load_stapling_file(const char * file,log_error_st * errh,buffer * b)1393 mod_openssl_load_stapling_file (const char *file, log_error_st *errh, buffer *b)
1394 {
1395 /* load stapling .der into buffer *b only if successful
1396 *
1397 * Note: for some TLS libs, the OCSP stapling response is not copied when
1398 * assigned to a session (and is reasonable since not changed frequently)
1399 * - BoringSSL SSL_set_ocsp_response()
1400 * - WolfSSL SSL_set_tlsext_status_ocsp_resp() (differs from OpenSSL API)
1401 * Therefore, there is a potential race condition if the OCSP response is
1402 * assigned to the session during the handshake and the Server Hello is
1403 * partially sent, AND (unlikely, if possible at all), the TLS library is
1404 * in the middle of reading this OSCP response buffer. If the OCSP response
1405 * is replaced due to an updated ssl.stapling-file (checked periodically),
1406 * AND the buffer is resized, this would be a problem. Resizing the buffer
1407 * is unlikely since updated OSCP response for same certificate are
1408 * typically the same size with the signature and dates refreshed.
1409 */
1410
1411 /* load raw .der file */
1412 off_t dlen = 1*1024*1024;/*(arbitrary limit: 1 MB file; expect < 1 KB)*/
1413 char *data = fdevent_load_file(file, &dlen, errh, malloc, free);
1414 if (NULL == data) return NULL;
1415
1416 if (NULL == b)
1417 b = buffer_init();
1418 else if (b->ptr)
1419 free(b->ptr);
1420 b->ptr = data;
1421 b->used = (uint32_t)dlen;
1422 b->size = (uint32_t)dlen+1;
1423 return b;
1424 }
1425
1426
1427 static unix_time64_t
mod_openssl_asn1_time_to_posix(const ASN1_TIME * asn1time)1428 mod_openssl_asn1_time_to_posix (const ASN1_TIME *asn1time)
1429 {
1430 #if LIBWOLFSSL_VERSION_HEX >= 0x05000000 /*(stub func filled in v5.0.0)*/
1431 /* Note: up to at least wolfSSL 4.5.0 (current version as this is written)
1432 * wolfSSL_ASN1_TIME_diff() is a stub function which always returns 0 */
1433 /* Note: this does not check for integer overflow of time_t! */
1434 int day, sec;
1435 return wolfSSL_ASN1_TIME_diff(&day, &sec, NULL, asn1time)
1436 ? log_epoch_secs + day*86400 + sec
1437 : -1;
1438 #else
1439 UNUSED(asn1time);
1440 return -1;
1441 #endif
1442 }
1443
1444
1445 static unix_time64_t
mod_openssl_ocsp_next_update(plugin_cert * pc)1446 mod_openssl_ocsp_next_update (plugin_cert *pc)
1447 {
1448 #if LIBWOLFSSL_VERSION_HEX < 0x05000000
1449 UNUSED(pc);
1450 (void)mod_openssl_asn1_time_to_posix(NULL);
1451 return -1; /*(not implemented)*/
1452 #else
1453 buffer *der = pc->ssl_stapling;
1454 const unsigned char *p = (unsigned char *)der->ptr; /*(p gets modified)*/
1455 OCSP_RESPONSE *ocsp = d2i_OCSP_RESPONSE(NULL, &p, buffer_clen(der));
1456 if (NULL == ocsp) return -1;
1457 OCSP_BASICRESP *bs = OCSP_response_get1_basic(ocsp);
1458 if (NULL == bs) {
1459 OCSP_RESPONSE_free(ocsp);
1460 return -1;
1461 }
1462
1463 /* XXX: should save and evaluate cert status returned by these calls */
1464 ASN1_TIME *nextupd = NULL;
1465 #if LIBWOLFSSL_VERSION_HEX < 0x04006000
1466 /* WolfSSL does not provide OCSP_resp_get0() OCSP_single_get0_status() */
1467 /* (inactive code path; alternative path followed in #if above for WolfSSL)
1468 * (chain not currently available in mod_openssl when used with WolfSSL)
1469 * (For WolfSSL, pc->ssl_pemfile_chain might not be filled in with actual
1470 * chain, but is used to store (buffer **) of DER decoded from PEM certs
1471 * read from ssl.pemfile, which may be a single cert, pc->ssl_pemfile_x509.
1472 * The chain is not calculated or filled in if single cert, and neither are
1473 * (X509 *), though (X509 *) could be temporarily created to calculated
1474 * (OCSP_CERTID *), which additionally could be calculated once at startup)
1475 */
1476 OCSP_CERTID *id = (NULL != pc->ssl_pemfile_chain)
1477 ? OCSP_cert_to_id(NULL, pc->ssl_pemfile_x509,
1478 sk_X509_value(pc->ssl_pemfile_chain, 0))
1479 : NULL;
1480 if (id == NULL) {
1481 OCSP_BASICRESP_free(bs);
1482 OCSP_RESPONSE_free(ocsp);
1483 return -1;
1484 }
1485 OCSP_resp_find_status(bs, id, NULL, NULL, NULL, NULL, &nextupd);
1486 OCSP_CERTID_free(id);
1487 #else
1488 OCSP_single_get0_status(OCSP_resp_get0(bs, 0), NULL, NULL, NULL, &nextupd);
1489 #endif
1490 unix_time64_t t = nextupd ? mod_openssl_asn1_time_to_posix(nextupd) : -1;
1491
1492 /* Note: trust external process which creates ssl.stapling-file to verify
1493 * (as well as to validate certificate status)
1494 * future: verify OCSP response here to double-check */
1495
1496 OCSP_BASICRESP_free(bs);
1497 OCSP_RESPONSE_free(ocsp);
1498
1499 return t;
1500 #endif
1501 }
1502
1503
1504 __attribute_cold__
1505 static void
mod_openssl_expire_stapling_file(server * srv,plugin_cert * pc)1506 mod_openssl_expire_stapling_file (server *srv, plugin_cert *pc)
1507 {
1508 if (NULL == pc->ssl_stapling) /*(previously discarded or never loaded)*/
1509 return;
1510
1511 /* discard expired OCSP stapling response */
1512 buffer_free(pc->ssl_stapling);
1513 pc->ssl_stapling = NULL;
1514 if (pc->must_staple)
1515 log_error(srv->errh, __FILE__, __LINE__,
1516 "certificate marked OCSP Must-Staple, "
1517 "but OCSP response expired from ssl.stapling-file %s",
1518 pc->ssl_stapling_file->ptr);
1519 }
1520
1521
1522 static int
mod_openssl_reload_stapling_file(server * srv,plugin_cert * pc,const unix_time64_t cur_ts)1523 mod_openssl_reload_stapling_file (server *srv, plugin_cert *pc, const unix_time64_t cur_ts)
1524 {
1525 buffer *b = mod_openssl_load_stapling_file(pc->ssl_stapling_file->ptr,
1526 srv->errh, pc->ssl_stapling);
1527 if (!b) return 0;
1528
1529 pc->ssl_stapling = b; /*(unchanged unless orig was NULL)*/
1530 pc->ssl_stapling_loadts = cur_ts;
1531 pc->ssl_stapling_nextts = mod_openssl_ocsp_next_update(pc);
1532 if (pc->ssl_stapling_nextts == -1) {
1533 /* "Next Update" might not be provided by OCSP responder
1534 * Use 3600 sec (1 hour) in that case. */
1535 /* retry in 1 hour if unable to determine Next Update */
1536 pc->ssl_stapling_nextts = cur_ts + 3600;
1537 pc->ssl_stapling_loadts = 0;
1538 }
1539 else if (pc->ssl_stapling_nextts < cur_ts) {
1540 mod_openssl_expire_stapling_file(srv, pc);
1541 return 0;
1542 }
1543
1544 return 1;
1545 }
1546
1547
1548 static int
mod_openssl_refresh_stapling_file(server * srv,plugin_cert * pc,const unix_time64_t cur_ts)1549 mod_openssl_refresh_stapling_file (server *srv, plugin_cert *pc, const unix_time64_t cur_ts)
1550 {
1551 if (pc->ssl_stapling && pc->ssl_stapling_nextts > cur_ts + 256)
1552 return 1; /* skip check for refresh unless close to expire */
1553 struct stat st;
1554 if (0 != stat(pc->ssl_stapling_file->ptr, &st)
1555 || TIME64_CAST(st.st_mtime) <= pc->ssl_stapling_loadts) {
1556 if (pc->ssl_stapling && pc->ssl_stapling_nextts < cur_ts)
1557 mod_openssl_expire_stapling_file(srv, pc);
1558 return 1;
1559 }
1560 return mod_openssl_reload_stapling_file(srv, pc, cur_ts);
1561 }
1562
1563
1564 static void
mod_openssl_refresh_stapling_files(server * srv,const plugin_data * p,const unix_time64_t cur_ts)1565 mod_openssl_refresh_stapling_files (server *srv, const plugin_data *p, const unix_time64_t cur_ts)
1566 {
1567 /* future: might construct array of (plugin_cert *) at startup
1568 * to avoid the need to search for them here */
1569 /* (init i to 0 if global context; to 1 to skip empty global context) */
1570 if (NULL == p->cvlist) return;
1571 for (int i = !p->cvlist[0].v.u2[1], used = p->nconfig; i < used; ++i) {
1572 const config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0];
1573 for (; cpv->k_id != -1; ++cpv) {
1574 if (cpv->k_id != 0) continue; /* k_id == 0 for ssl.pemfile */
1575 if (cpv->vtype != T_CONFIG_LOCAL) continue;
1576 plugin_cert *pc = cpv->v.v;
1577 if (pc->ssl_stapling_file)
1578 mod_openssl_refresh_stapling_file(srv, pc, cur_ts);
1579 }
1580 }
1581 }
1582
1583
1584 static int
mod_openssl_crt_must_staple(const WOLFSSL_X509 * crt)1585 mod_openssl_crt_must_staple (const WOLFSSL_X509 *crt)
1586 {
1587 #if LIBWOLFSSL_VERSION_HEX < 0x05000000 /*(stub func filled in v5.0.0)*/
1588 /* wolfSSL_ASN1_INTEGER_get() is a stub func < v5.0.0; always returns 0 */
1589 UNUSED(crt);
1590 return 0;
1591 #else
1592 STACK_OF(ASN1_OBJECT) * const tlsf = (STACK_OF(ASN1_OBJECT)*)
1593 wolfSSL_X509_get_ext_d2i(crt, NID_tlsfeature, NULL, NULL);
1594 if (NULL == tlsf) return 0;
1595
1596 int rc = 0;
1597
1598 /* wolfSSL_sk_ASN1_INTEGER_num() not implemented */
1599 /* wolfSSL_sk_ASN1_INTEGER_value() not implemented */
1600 /* wolfSSL_sk_ASN1_INTEGER_pop_free() not implemented */
1601 #define wolfSSL_sk_ASN1_INTEGER_num(sk) wolfSSL_sk_num(sk)
1602 #define wolfSSL_sk_ASN1_INTEGER_value(sk, i) wolfSSL_sk_value(sk, i)
1603 #define wolfSSL_sk_ASN1_INTEGER_pop_free(sk, fn) wolfSSL_sk_pop_free(sk, fn)
1604
1605 for (int i = 0; i < wolfSSL_sk_ASN1_INTEGER_num(tlsf); ++i) {
1606 WOLFSSL_ASN1_INTEGER *ai = wolfSSL_sk_ASN1_INTEGER_value(tlsf, i);
1607 long tlsextid = wolfSSL_ASN1_INTEGER_get(ai);
1608 if (tlsextid == 5) { /* 5 = OCSP Must-Staple */
1609 rc = 1;
1610 break;
1611 }
1612 }
1613
1614 wolfSSL_sk_ASN1_INTEGER_pop_free(tlsf, (wolfSSL_sk_freefunc)
1615 wolfSSL_ASN1_INTEGER_free);
1616 return rc; /* 1 if OCSP Must-Staple found; 0 if not */
1617 #endif
1618 }
1619
1620 #endif /* HAVE_OCSP */
1621
1622
1623 static plugin_cert *
network_openssl_load_pemfile(server * srv,const buffer * pemfile,const buffer * privkey,const buffer * ssl_stapling_file)1624 network_openssl_load_pemfile (server *srv, const buffer *pemfile, const buffer *privkey, const buffer *ssl_stapling_file)
1625 {
1626 if (!mod_openssl_init_once_openssl(srv)) return NULL;
1627
1628 buffer **ssl_pemfile_chain = NULL;
1629 buffer *ssl_pemfile_x509 =
1630 mod_wolfssl_load_pem_file(pemfile->ptr, srv->errh, &ssl_pemfile_chain);
1631 if (NULL == ssl_pemfile_x509) {
1632 #if defined(__clang_analyzer__) || defined(__COVERITY__)
1633 mod_wolfssl_free_der_certs(ssl_pemfile_chain); /*unnecessary*/
1634 #endif
1635 return NULL;
1636 }
1637
1638 buffer *ssl_pemfile_pkey =
1639 mod_wolfssl_evp_pkey_load_pem_file(privkey->ptr, srv->errh);
1640 if (NULL == ssl_pemfile_pkey) {
1641 /*buffer_free(ssl_pemfile_x509);*//*(part of chain)*/
1642 mod_wolfssl_free_der_certs(ssl_pemfile_chain);
1643 return NULL;
1644 }
1645
1646 /* wolfSSL_X509_check_private_key() is a stub func (not implemented) in
1647 * WolfSSL prior to v4.6.0, and still no-op #ifdef NO_CHECK_PRIVATE_KEY */
1648
1649 plugin_cert *pc = ck_malloc(sizeof(plugin_cert));
1650 pc->ssl_pemfile_pkey = ssl_pemfile_pkey;
1651 pc->ssl_pemfile_x509 = ssl_pemfile_x509;
1652 pc->ssl_pemfile_chain= ssl_pemfile_chain;
1653 pc->ssl_pemfile = pemfile;
1654 pc->ssl_privkey = privkey;
1655 pc->ssl_stapling = NULL;
1656 pc->ssl_stapling_file= ssl_stapling_file;
1657 pc->ssl_stapling_loadts = 0;
1658 pc->ssl_stapling_nextts = 0;
1659 #ifdef HAVE_OCSP
1660 WOLFSSL_X509 *crt =
1661 wolfSSL_X509_load_certificate_buffer((const unsigned char *)
1662 ssl_pemfile_x509->ptr,
1663 (int)buffer_clen(ssl_pemfile_x509),
1664 WOLFSSL_FILETYPE_ASN1);
1665 pc->must_staple = mod_openssl_crt_must_staple(crt);
1666 wolfSSL_X509_free(crt);
1667 #else
1668 pc->must_staple = 0;
1669 #endif
1670
1671 if (pc->ssl_stapling_file) {
1672 #ifdef HAVE_OCSP
1673 if (!mod_openssl_reload_stapling_file(srv, pc, log_epoch_secs)) {
1674 /* continue without OCSP response if there is an error */
1675 }
1676 #else
1677 log_error(srv->errh, __FILE__, __LINE__, "SSL:"
1678 "OCSP stapling not supported; ignoring %s",
1679 pc->ssl_stapling_file->ptr);
1680 #endif
1681 }
1682 else if (pc->must_staple) {
1683 log_error(srv->errh, __FILE__, __LINE__,
1684 "certificate %s marked OCSP Must-Staple, "
1685 "but ssl.stapling-file not provided", pemfile->ptr);
1686 }
1687
1688 #if 0
1689 #if LIBWOLFSSL_VERSION_HEX >= 0x05000000 /*(stub func filled in v5.0.0)*/
1690 pc->notAfter = /*(see mod_wolfssl_cert_is_active to get X509 crt from buf)*/
1691 mod_openssl_asn1_time_to_posix(wolfSSL_X509_get_notAfter(crt));
1692 #endif
1693 #endif
1694
1695 return pc;
1696 }
1697
1698
1699 #ifdef HAVE_TLS_EXTENSIONS
1700
1701 #ifdef HAVE_ALPN
1702 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1703
1704 static int
mod_openssl_acme_tls_1(SSL * ssl,handler_ctx * hctx)1705 mod_openssl_acme_tls_1 (SSL *ssl, handler_ctx *hctx)
1706 {
1707 buffer * const b = hctx->tmp_buf;
1708 const buffer * const name = &hctx->r->uri.authority;
1709 log_error_st * const errh = hctx->r->conf.errh;
1710 buffer *ssl_pemfile_x509 = NULL;
1711 buffer *ssl_pemfile_pkey = NULL;
1712 buffer **ssl_pemfile_chain = NULL;
1713 size_t len;
1714 int rc = SSL_TLSEXT_ERR_ALERT_FATAL;
1715
1716 /* check if acme-tls/1 protocol is enabled (path to dir of cert(s) is set)*/
1717 if (!hctx->conf.ssl_acme_tls_1)
1718 return SSL_TLSEXT_ERR_NOACK; /*(reuse value here for not-configured)*/
1719
1720 /* check if SNI set server name (required for acme-tls/1 protocol)
1721 * and perform simple path checks for no '/'
1722 * and no leading '.' (e.g. ignore "." or ".." or anything beginning '.') */
1723 if (buffer_is_blank(name)) return rc;
1724 if (NULL != strchr(name->ptr, '/')) return rc;
1725 if (name->ptr[0] == '.') return rc;
1726 #if 0
1727 if (0 != http_request_host_policy(name,hctx->r->conf.http_parseopts,443))
1728 return rc;
1729 #endif
1730 buffer_copy_path_len2(b, BUF_PTR_LEN(hctx->conf.ssl_acme_tls_1),
1731 BUF_PTR_LEN(name));
1732 len = buffer_clen(b);
1733
1734 do {
1735 buffer_append_string_len(b, CONST_STR_LEN(".crt.pem"));
1736 ssl_pemfile_x509 =
1737 mod_wolfssl_load_pem_file(b->ptr, errh, &ssl_pemfile_chain);
1738 if (NULL == ssl_pemfile_x509) {
1739 log_error(errh, __FILE__, __LINE__,
1740 "SSL: Failed to load acme-tls/1 pemfile: %s", b->ptr);
1741 break;
1742 }
1743
1744 buffer_truncate(b, len); /*(remove ".crt.pem")*/
1745 buffer_append_string_len(b, CONST_STR_LEN(".key.pem"));
1746 ssl_pemfile_pkey = mod_wolfssl_evp_pkey_load_pem_file(b->ptr, errh);
1747 if (NULL == ssl_pemfile_pkey) {
1748 log_error(errh, __FILE__, __LINE__,
1749 "SSL: Failed to load acme-tls/1 pemfile: %s", b->ptr);
1750 break;
1751 }
1752
1753 #if 0 /* redundant with below? */
1754 if (!X509_check_private_key(ssl_pemfile_x509, ssl_pemfile_pkey)) {
1755 log_error(errh, __FILE__, __LINE__,
1756 "SSL: Private key does not match acme-tls/1 "
1757 "certificate public key, reason: %s %s"
1758 ERR_error_string(ERR_get_error(), NULL), b->ptr);
1759 break;
1760 }
1761 #endif
1762
1763 /* first set certificate!
1764 * setting private key checks whether certificate matches it */
1765 buffer *cert = ssl_pemfile_x509;
1766 if (1 != wolfSSL_use_certificate_ASN1(ssl, (unsigned char *)cert->ptr,
1767 (int)buffer_clen(cert))){
1768 log_error(errh, __FILE__, __LINE__,
1769 "SSL: failed to set acme-tls/1 certificate for TLS server "
1770 "name %s: %s", name->ptr, ERR_error_string(ERR_get_error(),NULL));
1771 break;
1772 }
1773
1774 if (ssl_pemfile_chain) {
1775 /* WolfSSL limitation */
1776 /* WolfSSL does not support setting per-session chain;
1777 * limitation is to per-CTX chain, and so chain is not provided for
1778 * "acme-tls/1" (might be non-issue; chain might not be present) */
1779 }
1780
1781 buffer *pkey = ssl_pemfile_pkey;
1782 if (1 != wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char *)pkey->ptr,
1783 (int)buffer_clen(pkey),
1784 WOLFSSL_FILETYPE_ASN1)) {
1785 log_error(errh, __FILE__, __LINE__,
1786 "SSL: failed to set acme-tls/1 private key for TLS server "
1787 "name %s: %s", name->ptr, ERR_error_string(ERR_get_error(),NULL));
1788 break;
1789 }
1790
1791 hctx->conf.ssl_verifyclient_enforce = 0;
1792 wolfSSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
1793 rc = SSL_TLSEXT_ERR_OK;
1794 } while (0);
1795
1796 if (ssl_pemfile_pkey) {
1797 wolfSSL_OPENSSL_cleanse(b->ptr, b->size);
1798 buffer_free(ssl_pemfile_pkey);
1799 }
1800 /*if (ssl_pemfile_x509) buffer_free(ssl_pemfile_x509);*//*(part of chain)*/
1801 mod_wolfssl_free_der_certs(ssl_pemfile_chain);
1802
1803 return rc;
1804 }
1805
1806 static int
mod_openssl_alpn_h2_policy(handler_ctx * const hctx)1807 mod_openssl_alpn_h2_policy (handler_ctx * const hctx)
1808 {
1809 /*(currently called after handshake has completed)*/
1810 #if 0 /* SNI omitted by client when connecting to IP instead of to name */
1811 if (buffer_is_blank(&hctx->r->uri.authority)) {
1812 log_error(hctx->errh, __FILE__, __LINE__,
1813 "SSL: error ALPN h2 without SNI");
1814 return -1;
1815 }
1816 #endif
1817 if (wolfSSL_version(hctx->ssl) < TLS1_2_VERSION) {
1818 log_error(hctx->errh, __FILE__, __LINE__,
1819 "SSL: error ALPN h2 requires TLSv1.2 or later");
1820 return -1;
1821 }
1822
1823 return 0;
1824 }
1825
1826 /* https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids */
1827 static int
mod_openssl_alpn_select_cb(SSL * ssl,const unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned int inlen,void * arg)1828 mod_openssl_alpn_select_cb (SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
1829 {
1830 handler_ctx *hctx = (handler_ctx *) SSL_get_app_data(ssl);
1831 unsigned short proto;
1832 UNUSED(arg);
1833
1834 for (unsigned int i = 0, n; i < inlen; i += n) {
1835 n = in[i++];
1836 if (i+n > inlen || 0 == n) break;
1837 switch (n) {
1838 case 2: /* "h2" */
1839 if (in[i] == 'h' && in[i+1] == '2') {
1840 if (!hctx->r->conf.h2proto) continue;
1841 proto = MOD_OPENSSL_ALPN_H2;
1842 if (hctx->r->handler_module == NULL)/*(e.g. not mod_sockproxy)*/
1843 hctx->r->http_version = HTTP_VERSION_2;
1844 break;
1845 }
1846 continue;
1847 case 8: /* "http/1.1" "http/1.0" */
1848 if (0 == memcmp(in+i, "http/1.", 7)) {
1849 if (in[i+7] == '1') {
1850 proto = MOD_OPENSSL_ALPN_HTTP11;
1851 break;
1852 }
1853 if (in[i+7] == '0') {
1854 proto = MOD_OPENSSL_ALPN_HTTP10;
1855 break;
1856 }
1857 }
1858 continue;
1859 case 10: /* "acme-tls/1" */
1860 if (0 == memcmp(in+i, "acme-tls/1", 10)) {
1861 int rc = mod_openssl_acme_tls_1(ssl, hctx);
1862 if (rc == SSL_TLSEXT_ERR_OK) {
1863 proto = MOD_OPENSSL_ALPN_ACME_TLS_1;
1864 break;
1865 }
1866 /* (use SSL_TLSEXT_ERR_NOACK for not-configured) */
1867 if (rc == SSL_TLSEXT_ERR_NOACK) continue;
1868 return rc;
1869 }
1870 continue;
1871 default:
1872 continue;
1873 }
1874
1875 hctx->alpn = proto;
1876 *out = in+i;
1877 *outlen = n;
1878 return SSL_TLSEXT_ERR_OK;
1879 }
1880
1881 return SSL_TLSEXT_ERR_NOACK;
1882 }
1883
1884 #endif /* TLSEXT_TYPE_application_layer_protocol_negotiation */
1885 #endif /* HAVE_ALPN */
1886
1887 #endif /* HAVE_TLS_EXTENSIONS */
1888
1889
1890 static int
1891 mod_openssl_ssl_conf_cmd (server *srv, plugin_config_socket *s);
1892
1893
1894 #ifndef NO_DH
1895 #include <wolfssl/openssl/dh.h>
1896 /* wolfSSL provides wolfSSL_DH_set0_pqg() for
1897 * Apache w/ OPENSSL_VERSION_NUMBER >= 0x10100000L
1898 * but does not provide most other openssl 1.1.0+ interfaces
1899 * and get_dh2048() might not be necessary if wolfSSL defines
1900 * HAVE_TLS_EXTENSIONS HAVE_DH_DEFAULT_PARAMS HAVE_FFDHE HAVE_SUPPORTED_CURVES*/
1901 #ifndef DH_set0_pqg /*(added in wolfssl v5.0.0)*/
1902 #define DH_set0_pqg(dh, dh_p, NULL, dh_g) \
1903 ((dh)->p = (dh_p), (dh)->g = (dh_g), (dh_p) != NULL && (dh_g) != NULL)
1904 #endif
1905 /* https://tools.ietf.org/html/rfc7919#appendix-A.1
1906 * A.1. ffdhe2048
1907 *
1908 * https://ssl-config.mozilla.org/ffdhe2048.txt
1909 * C code generated with: openssl dhparam -C -in ffdhe2048.txt
1910 */
get_dh2048(void)1911 static DH *get_dh2048(void)
1912 {
1913 static unsigned char dhp_2048[] = {
1914 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAD, 0xF8,
1915 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, 0xAF, 0xDC, 0x56, 0x20,
1916 0x27, 0x3D, 0x3C, 0xF1, 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D,
1917 0x36, 0x95, 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB,
1918 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, 0x7D, 0x2F,
1919 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, 0xF6, 0x81, 0xB2, 0x02,
1920 0xAE, 0xC4, 0x61, 0x7A, 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD,
1921 0x65, 0x61, 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0,
1922 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, 0xB5, 0x57,
1923 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, 0x98, 0x4F, 0x0C, 0x70,
1924 0xE0, 0xE6, 0x8B, 0x77, 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF,
1925 0xE8, 0x72, 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
1926 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, 0xBC, 0x0A,
1927 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, 0xD1, 0x08, 0xA9, 0x4B,
1928 0xB2, 0xC8, 0xE3, 0xFB, 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7,
1929 0xF4, 0x68, 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4,
1930 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, 0x0B, 0x07,
1931 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, 0x9E, 0x02, 0xFC, 0xE1,
1932 0xCD, 0xF7, 0xE2, 0xEC, 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34,
1933 0x2F, 0x61, 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF,
1934 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, 0xC3, 0xFE,
1935 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, 0x3B, 0xB5, 0xFC, 0xBC,
1936 0x2E, 0xC2, 0x20, 0x05, 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16,
1937 0x83, 0xB2, 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
1938 0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, 0xFF, 0xFF,
1939 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
1940 };
1941 static unsigned char dhg_2048[] = {
1942 0x02
1943 };
1944 DH *dh = DH_new();
1945 BIGNUM *p, *g;
1946
1947 if (dh == NULL)
1948 return NULL;
1949 p = BN_bin2bn(dhp_2048, sizeof(dhp_2048), NULL);
1950 g = BN_bin2bn(dhg_2048, sizeof(dhg_2048), NULL);
1951 if (p == NULL || g == NULL || !DH_set0_pqg(dh, p, NULL, g)) {
1952 DH_free(dh);
1953 BN_free(p);
1954 BN_free(g);
1955 return NULL;
1956 }
1957 return dh;
1958 }
1959 #endif
1960
1961
1962 static int
mod_openssl_ssl_conf_dhparameters(server * srv,plugin_config_socket * s,const buffer * dhparameters)1963 mod_openssl_ssl_conf_dhparameters(server *srv, plugin_config_socket *s, const buffer *dhparameters)
1964 {
1965 #ifndef NO_DH
1966 DH *dh;
1967 /* Support for Diffie-Hellman key exchange */
1968 if (dhparameters) {
1969 const char *fn = dhparameters->ptr;
1970 off_t dlen = 1*1024*1024;/*(arbitrary limit: 1 MB; expect < 1 KB)*/
1971 char *data = fdevent_load_file(fn, &dlen, srv->errh, malloc, free);
1972 int rc = (NULL != data) ? 0 : -1;
1973 if (0 == rc)
1974 wolfSSL_CTX_SetTmpDH_buffer(s->ssl_ctx, (unsigned char *)data,
1975 (long)dlen, WOLFSSL_FILETYPE_PEM);
1976 if (dlen) ck_memzero(data, dlen);
1977 free(data);
1978 if (rc < 0) {
1979 log_error(srv->errh, __FILE__, __LINE__,
1980 "SSL: Unable to read DH params from file %s",
1981 dhparameters->ptr);
1982 return 0;
1983 }
1984 }
1985 else {
1986 dh = get_dh2048();
1987 if (dh == NULL) {
1988 log_error(srv->errh, __FILE__, __LINE__,
1989 "SSL: get_dh2048() failed");
1990 return 0;
1991 }
1992 SSL_CTX_set_tmp_dh(s->ssl_ctx, dh);
1993 DH_free(dh);
1994 }
1995 SSL_CTX_set_options(s->ssl_ctx, SSL_OP_SINGLE_DH_USE);
1996 #else
1997 if (dhparameters) {
1998 log_error(srv->errh, __FILE__, __LINE__,
1999 "SSL: wolfssl compiled without DH support, "
2000 "can't load parameters from %s", dhparameters->ptr);
2001 }
2002 #endif
2003
2004 return 1;
2005 }
2006
2007
2008 static int
mod_openssl_ssl_conf_curves(server * srv,plugin_config_socket * s,const buffer * ssl_ec_curve)2009 mod_openssl_ssl_conf_curves(server *srv, plugin_config_socket *s, const buffer *ssl_ec_curve)
2010 {
2011 /* Support for Elliptic-Curve Diffie-Hellman key exchange */
2012 /* OpenSSL only supports the "named curves" from RFC 4492, section 5.1.1. */
2013 const char *curve = ssl_ec_curve ? ssl_ec_curve->ptr : "prime256v1";
2014 int nid = wolfSSL_OBJ_sn2nid(curve);
2015 if (nid) {
2016 EC_KEY * const ecdh = EC_KEY_new_by_curve_name(nid);
2017 if (ecdh == NULL) {
2018 log_error(srv->errh, __FILE__, __LINE__,
2019 "SSL: Unable to create curve %s", curve);
2020 return 0;
2021 }
2022 wolfSSL_SSL_CTX_set_tmp_ecdh(s->ssl_ctx, ecdh);
2023 SSL_CTX_set_options(s->ssl_ctx, SSL_OP_SINGLE_ECDH_USE);
2024 EC_KEY_free(ecdh);
2025 return 1;
2026 }
2027 else {
2028 log_error(srv->errh, __FILE__, __LINE__,
2029 "SSL: Unknown curve name %s", curve);
2030 return 0;
2031 }
2032 }
2033
2034
2035 static int
network_init_ssl(server * srv,plugin_config_socket * s,plugin_data * p)2036 network_init_ssl (server *srv, plugin_config_socket *s, plugin_data *p)
2037 {
2038 /* load SSL certificates */
2039
2040 #ifndef SSL_OP_NO_COMPRESSION
2041 #define SSL_OP_NO_COMPRESSION 0
2042 #endif
2043 long ssloptions = SSL_OP_ALL
2044 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
2045 | SSL_OP_NO_COMPRESSION;
2046
2047 #if LIBWOLFSSL_VERSION_HEX >= 0x04002000
2048 s->ssl_ctx = SSL_CTX_new(TLS_server_method());
2049 #else
2050 s->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
2051 #endif
2052 if (NULL == s->ssl_ctx) {
2053 log_error(srv->errh, __FILE__, __LINE__,
2054 "SSL: %s", ERR_error_string(ERR_get_error(), NULL));
2055 return -1;
2056 }
2057
2058 #ifdef SSL_OP_NO_RENEGOTIATION /* openssl 1.1.0 */
2059 ssloptions |= SSL_OP_NO_RENEGOTIATION;
2060 #endif
2061
2062 /* completely useless identifier;
2063 * required for client cert verification to work with sessions */
2064 if (0 == SSL_CTX_set_session_id_context(
2065 s->ssl_ctx,(const unsigned char*)CONST_STR_LEN("lighttpd"))){
2066 log_error(srv->errh, __FILE__, __LINE__,
2067 "SSL: failed to set session context: %s",
2068 ERR_error_string(ERR_get_error(), NULL));
2069 return -1;
2070 }
2071
2072 #if !defined(NO_SESSION_CACHE)
2073 const int disable_sess_cache =
2074 !config_feature_bool(srv, "ssl.session-cache", 0);
2075 if (disable_sess_cache)
2076 /* disable session cache; session tickets are preferred */
2077 SSL_CTX_set_session_cache_mode(s->ssl_ctx,
2078 SSL_SESS_CACHE_OFF
2079 | SSL_SESS_CACHE_NO_AUTO_CLEAR
2080 | SSL_SESS_CACHE_NO_INTERNAL);
2081 #endif
2082
2083 SSL_CTX_set_options(s->ssl_ctx, ssloptions);
2084 SSL_CTX_set_info_callback(s->ssl_ctx, ssl_info_callback);
2085
2086 /*(wolfSSL does not support SSLv2)*/
2087
2088 if (0 != SSL_OP_NO_SSLv3) {
2089 /* disable SSLv3 */
2090 if ((SSL_OP_NO_SSLv3
2091 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv3))
2092 != SSL_OP_NO_SSLv3) {
2093 log_error(srv->errh, __FILE__, __LINE__,
2094 "SSL: %s", ERR_error_string(ERR_get_error(), NULL));
2095 return -1;
2096 }
2097 }
2098
2099 if (s->ssl_cipher_list) {
2100 /* Disable support for low encryption ciphers */
2101 if (SSL_CTX_set_cipher_list(s->ssl_ctx,s->ssl_cipher_list->ptr)!=1){
2102 log_error(srv->errh, __FILE__, __LINE__,
2103 "SSL: %s", ERR_error_string(ERR_get_error(), NULL));
2104 return -1;
2105 }
2106
2107 if (s->ssl_honor_cipher_order) {
2108 SSL_CTX_set_options(s->ssl_ctx,SSL_OP_CIPHER_SERVER_PREFERENCE);
2109 }
2110 }
2111
2112 #ifdef SSL_OP_PRIORITIZE_CHACHA /*(openssl 1.1.1)*/
2113 if (s->ssl_honor_cipher_order)
2114 SSL_CTX_set_options(s->ssl_ctx, SSL_OP_PRIORITIZE_CHACHA);
2115 #endif
2116
2117 if (!mod_openssl_ssl_conf_dhparameters(srv, s, NULL))
2118 return -1;
2119
2120 #ifdef HAVE_SESSION_TICKET
2121 wolfSSL_CTX_set_tlsext_ticket_key_cb(s->ssl_ctx, ssl_tlsext_ticket_key_cb);
2122 #endif
2123
2124 #ifdef HAVE_OCSP
2125 wolfSSL_CTX_set_tlsext_status_cb(s->ssl_ctx, ssl_tlsext_status_cb);
2126 #endif
2127
2128 /* load all ssl.ca-files specified in the config into each SSL_CTX
2129 * XXX: This might be a bit excessive, but are all trusted CAs
2130 * TODO: prefer to load on-demand in mod_openssl_cert_cb()
2131 * for openssl >= 1.0.2 */
2132 if (!mod_wolfssl_load_ca_files(s->ssl_ctx, p, srv))
2133 return -1;
2134
2135 if (s->ssl_verifyclient) {
2136 if (NULL == s->ssl_ca_file) {
2137 log_error(srv->errh, __FILE__, __LINE__,
2138 "SSL: You specified ssl.verifyclient.activate "
2139 "but no ssl.verifyclient.ca-file");
2140 return -1;
2141 }
2142 #ifndef OPENSSL_ALL
2143 log_error(srv->errh, __FILE__, __LINE__,
2144 "SSL: You specified ssl.verifyclient.activate "
2145 "but wolfssl library built without necessary support");
2146 return -1;
2147 #else
2148 /* Before wolfssl 4.6.0, wolfSSL_dup_CA_list() is a stub function
2149 * which returns NULL, so DN names in cert request are not set here.
2150 * (A patch has been submitted to WolfSSL add is part of 4.6.0)
2151 * https://github.com/wolfSSL/wolfssl/pull/3098 */
2152 STACK_OF(X509_NAME) * const cert_names = s->ssl_ca_dn_file
2153 ? s->ssl_ca_dn_file
2154 : s->ssl_ca_file->names;
2155 wolfSSL_CTX_set_client_CA_list(s->ssl_ctx,
2156 wolfSSL_dup_CA_list(cert_names));
2157 int mode = SSL_VERIFY_PEER;
2158 if (s->ssl_verifyclient_enforce) {
2159 mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2160 }
2161 wolfSSL_CTX_set_verify(s->ssl_ctx, mode, verify_callback);
2162 wolfSSL_CTX_set_verify_depth(s->ssl_ctx,
2163 s->ssl_verifyclient_depth + 1);
2164 #endif
2165 if (s->ssl_ca_crl_file) {
2166 if (!mod_wolfssl_load_cacrls(s->ssl_ctx,s->ssl_ca_crl_file,srv))
2167 return -1;
2168 }
2169 }
2170
2171 if (1 != mod_wolfssl_CTX_use_certificate_chain_file(
2172 s->ssl_ctx, s->pc->ssl_pemfile->ptr, srv->errh))
2173 return -1;
2174
2175 buffer *k = s->pc->ssl_pemfile_pkey;
2176 if (1 != wolfSSL_CTX_use_PrivateKey_buffer(s->ssl_ctx,
2177 (unsigned char *)k->ptr,
2178 (int)buffer_clen(k),
2179 WOLFSSL_FILETYPE_ASN1)) {
2180 log_error(srv->errh, __FILE__, __LINE__,
2181 "SSL: %s %s %s", ERR_error_string(ERR_get_error(), NULL),
2182 s->pc->ssl_pemfile->ptr, s->pc->ssl_privkey->ptr);
2183 return -1;
2184 }
2185
2186 if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
2187 log_error(srv->errh, __FILE__, __LINE__,
2188 "SSL: Private key does not match the certificate public key, "
2189 "reason: %s %s %s", ERR_error_string(ERR_get_error(), NULL),
2190 s->pc->ssl_pemfile->ptr, s->pc->ssl_privkey->ptr);
2191 return -1;
2192 }
2193
2194 SSL_CTX_set_default_read_ahead(s->ssl_ctx, s->ssl_read_ahead);
2195 wolfSSL_CTX_set_mode(s->ssl_ctx,
2196 SSL_MODE_ENABLE_PARTIAL_WRITE);
2197 wolfSSL_CTX_set_mode(s->ssl_ctx, /*(wolfSSL default mode)*/
2198 WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
2199 #ifdef wolfSSL_SSL_MODE_RELEASE_BUFFERS
2200 wolfSSL_CTX_set_mode(s->ssl_ctx, /*(not currently implemented)*/
2201 wolfSSL_SSL_MODE_RELEASE_BUFFERS);
2202 #endif
2203
2204 #ifdef HAVE_TLS_EXTENSIONS
2205 /*(wolfSSL preprocessor defines are obnoxious)*/
2206 /*(code should be HAVE_SNI, but is hidden by OPENSSL_ALL
2207 * even though the comment in wolfssl code on the #endif
2208 * says (OPENSSL_ALL
2209 * || (OPENSSL_EXTRA
2210 * && (HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_LIGHTY)))
2211 * and sniRecvCb sniRecvCbArg are hidden by *different* set of defines
2212 * in wolfssl/internal.h)
2213 * Note: wolfSSL SNI callbacks members not present unless wolfSSL is
2214 * built OPENSSL_ALL or some additional combination of preprocessor
2215 * defines. The following should work with more recent wolfSSL versions
2216 * (and HAVE_LIGHTY is not sufficient in wolfssl <= 4.5.0) */
2217 #if defined(OPENSSL_ALL) \
2218 || (defined(OPENSSL_EXTRA) \
2219 && (defined(HAVE_STUNNEL) \
2220 || defined(WOLFSSL_NGINX) \
2221 || defined(WOLFSSL_HAPROXY)))
2222 #else
2223 #undef HAVE_SNI
2224 #endif
2225 #ifdef HAVE_SNI
2226 wolfSSL_CTX_set_servername_callback(
2227 s->ssl_ctx, network_ssl_servername_callback);
2228 wolfSSL_CTX_set_servername_arg(s->ssl_ctx, srv);
2229 #else
2230 log_error(srv->errh, __FILE__, __LINE__,
2231 "SSL: WARNING: SNI callbacks *crippled* in wolfSSL library build");
2232 UNUSED(network_ssl_servername_callback);
2233 #endif
2234
2235 #ifdef HAVE_ALPN
2236 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
2237 SSL_CTX_set_alpn_select_cb(s->ssl_ctx,mod_openssl_alpn_select_cb,NULL);
2238 #endif
2239 #endif
2240 #endif
2241
2242 if (wolfSSL_CTX_SetMinVersion(s->ssl_ctx, WOLFSSL_TLSV1_2)
2243 != WOLFSSL_SUCCESS)
2244 return -1;
2245
2246 if (s->ssl_conf_cmd && s->ssl_conf_cmd->used) {
2247 if (0 != mod_openssl_ssl_conf_cmd(srv, s)) return -1;
2248 }
2249
2250 return 0;
2251 }
2252
2253
2254 /* expanded from:
2255 * $ openssl ciphers 'EECDH+AESGCM:AES256+EECDH:CHACHA20:!SHA1:!SHA256:!SHA384'
2256 */
2257 #define LIGHTTPD_DEFAULT_CIPHER_LIST \
2258 "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-CCM8:ECDHE-ECDSA-AES256-CCM:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:RSA-PSK-CHACHA20-POLY1305:DHE-PSK-CHACHA20-POLY1305:ECDHE-PSK-CHACHA20-POLY1305:PSK-CHACHA20-POLY1305"
2259
2260
2261 static int
mod_openssl_set_defaults_sockets(server * srv,plugin_data * p)2262 mod_openssl_set_defaults_sockets(server *srv, plugin_data *p)
2263 {
2264 static const config_plugin_keys_t cpk[] = {
2265 { CONST_STR_LEN("ssl.engine"),
2266 T_CONFIG_BOOL,
2267 T_CONFIG_SCOPE_SOCKET }
2268 ,{ CONST_STR_LEN("ssl.cipher-list"),
2269 T_CONFIG_STRING,
2270 T_CONFIG_SCOPE_SOCKET }
2271 ,{ CONST_STR_LEN("ssl.openssl.ssl-conf-cmd"),
2272 T_CONFIG_ARRAY_KVSTRING,
2273 T_CONFIG_SCOPE_SOCKET }
2274 ,{ CONST_STR_LEN("ssl.pemfile"), /* included to process global scope */
2275 T_CONFIG_STRING,
2276 T_CONFIG_SCOPE_CONNECTION }
2277 ,{ CONST_STR_LEN("ssl.stek-file"),
2278 T_CONFIG_STRING,
2279 T_CONFIG_SCOPE_SERVER }
2280 ,{ NULL, 0,
2281 T_CONFIG_UNSET,
2282 T_CONFIG_SCOPE_UNSET }
2283 };
2284 static const buffer default_ssl_cipher_list =
2285 { CONST_STR_LEN(LIGHTTPD_DEFAULT_CIPHER_LIST), 0 };
2286
2287 p->ssl_ctxs = ck_calloc(srv->config_context->used, sizeof(plugin_ssl_ctx));
2288
2289 int rc = HANDLER_GO_ON;
2290 plugin_data_base srvplug;
2291 memset(&srvplug, 0, sizeof(srvplug));
2292 plugin_data_base * const ps = &srvplug;
2293 if (!config_plugin_values_init(srv, ps, cpk, "mod_openssl"))
2294 return HANDLER_ERROR;
2295
2296 plugin_config_socket defaults;
2297 memset(&defaults, 0, sizeof(defaults));
2298 defaults.ssl_cipher_list = &default_ssl_cipher_list;
2299
2300 /* process and validate config directives for global and $SERVER["socket"]
2301 * (init i to 0 if global context; to 1 to skip empty global context) */
2302 for (int i = !ps->cvlist[0].v.u2[1]; i < ps->nconfig; ++i) {
2303 config_cond_info cfginfo;
2304 config_get_config_cond_info(&cfginfo, (uint32_t)ps->cvlist[i].k_id);
2305 int is_socket_scope = (0 == i || cfginfo.comp == COMP_SERVER_SOCKET);
2306 int count_not_engine = 0;
2307
2308 plugin_config_socket conf;
2309 memcpy(&conf, &defaults, sizeof(conf));
2310 config_plugin_value_t *cpv = ps->cvlist + ps->cvlist[i].v.u2[0];
2311 for (; -1 != cpv->k_id; ++cpv) {
2312 /* ignore ssl.pemfile (k_id=3); included to process global scope */
2313 if (!is_socket_scope && cpv->k_id != 3) {
2314 log_error(srv->errh, __FILE__, __LINE__,
2315 "%s is valid only in global scope or "
2316 "$SERVER[\"socket\"] condition", cpk[cpv->k_id].k);
2317 continue;
2318 }
2319 ++count_not_engine;
2320 switch (cpv->k_id) {
2321 case 0: /* ssl.engine */
2322 conf.ssl_enabled = (0 != cpv->v.u);
2323 --count_not_engine;
2324 break;
2325 case 1: /* ssl.cipher-list */
2326 if (!buffer_is_blank(cpv->v.b)) {
2327 conf.ssl_cipher_list = cpv->v.b;
2328 /*(historical use might list non-PFS ciphers)*/
2329 conf.ssl_honor_cipher_order = 1;
2330 log_error(srv->errh, __FILE__, __LINE__,
2331 "%s is deprecated. "
2332 "Please prefer lighttpd secure TLS defaults, or use "
2333 "ssl.openssl.ssl-conf-cmd \"CipherString\" to set custom "
2334 "cipher list.", cpk[cpv->k_id].k);
2335 }
2336 break;
2337 case 2: /* ssl.openssl.ssl-conf-cmd */
2338 *(const array **)&conf.ssl_conf_cmd = cpv->v.a;
2339 break;
2340 case 3: /* ssl.pemfile */
2341 /* ignore here; included to process global scope when
2342 * ssl.pemfile is set, but ssl.engine is not "enable" */
2343 break;
2344 case 4: /* ssl.stek-file */
2345 if (!buffer_is_blank(cpv->v.b))
2346 p->ssl_stek_file = cpv->v.b->ptr;
2347 break;
2348 default:/* should not happen */
2349 break;
2350 }
2351 }
2352 if (HANDLER_GO_ON != rc) break;
2353 if (0 == i) memcpy(&defaults, &conf, sizeof(conf));
2354
2355 if (0 != i && !conf.ssl_enabled) continue;
2356
2357 /* fill plugin_config_socket with global context then $SERVER["socket"]
2358 * only for directives directly in current $SERVER["socket"] condition*/
2359
2360 /*conf.pc = p->defaults.pc;*/
2361 conf.ssl_ca_file = p->defaults.ssl_ca_file;
2362 conf.ssl_ca_dn_file = p->defaults.ssl_ca_dn_file;
2363 conf.ssl_ca_crl_file = p->defaults.ssl_ca_crl_file;
2364 conf.ssl_verifyclient = p->defaults.ssl_verifyclient;
2365 conf.ssl_verifyclient_enforce = p->defaults.ssl_verifyclient_enforce;
2366 conf.ssl_verifyclient_depth = p->defaults.ssl_verifyclient_depth;
2367 conf.ssl_read_ahead = p->defaults.ssl_read_ahead;
2368
2369 int sidx = ps->cvlist[i].k_id;
2370 for (int j = !p->cvlist[0].v.u2[1]; j < p->nconfig; ++j) {
2371 if (p->cvlist[j].k_id != sidx) continue;
2372 /*if (0 == sidx) break;*//*(repeat to get ssl_pemfile,ssl_privkey)*/
2373 cpv = p->cvlist + p->cvlist[j].v.u2[0];
2374 for (; -1 != cpv->k_id; ++cpv) {
2375 ++count_not_engine;
2376 switch (cpv->k_id) {
2377 case 0: /* ssl.pemfile */
2378 if (cpv->vtype == T_CONFIG_LOCAL)
2379 conf.pc = cpv->v.v;
2380 break;
2381 case 2: /* ssl.ca-file */
2382 if (cpv->vtype == T_CONFIG_LOCAL)
2383 conf.ssl_ca_file = cpv->v.v;
2384 break;
2385 case 3: /* ssl.ca-dn-file */
2386 if (cpv->vtype == T_CONFIG_LOCAL)
2387 conf.ssl_ca_dn_file = cpv->v.v;
2388 break;
2389 case 4: /* ssl.ca-crl-file */
2390 if (!buffer_is_blank(cpv->v.b))
2391 conf.ssl_ca_crl_file = cpv->v.b;
2392 break;
2393 case 5: /* ssl.read-ahead */
2394 conf.ssl_read_ahead = (0 != cpv->v.u);
2395 break;
2396 case 6: /* ssl.disable-client-renegotiation */
2397 /*(ignored; unsafe renegotiation disabled by default)*/
2398 break;
2399 case 7: /* ssl.verifyclient.activate */
2400 conf.ssl_verifyclient = (0 != cpv->v.u);
2401 break;
2402 case 8: /* ssl.verifyclient.enforce */
2403 conf.ssl_verifyclient_enforce = (0 != cpv->v.u);
2404 break;
2405 case 9: /* ssl.verifyclient.depth */
2406 conf.ssl_verifyclient_depth = (unsigned char)cpv->v.shrt;
2407 break;
2408 #if 0 /*(cpk->k_id remapped in mod_openssl_set_defaults())*/
2409 case 15:/* ssl.verifyclient.ca-file */
2410 case 16:/* ssl.verifyclient.ca-dn-file */
2411 case 17:/* ssl.verifyclient.ca-crl-file */
2412 #endif
2413 default:
2414 break;
2415 }
2416 }
2417 break;
2418 }
2419
2420 if (NULL == conf.pc) {
2421 if (0 == i && !conf.ssl_enabled) continue;
2422 if (0 != i) {
2423 /* inherit ssl settings from global scope
2424 * (if only ssl.engine = "enable" and no other ssl.* settings)
2425 * (This is for convenience when defining both IPv4 and IPv6
2426 * and desiring to inherit the ssl config from global context
2427 * without having to duplicate the directives)*/
2428 if (count_not_engine
2429 || (conf.ssl_enabled && NULL == p->ssl_ctxs[0].ssl_ctx)) {
2430 log_error(srv->errh, __FILE__, __LINE__,
2431 "ssl.pemfile has to be set in same $SERVER[\"socket\"] scope "
2432 "as other ssl.* directives, unless only ssl.engine is set, "
2433 "inheriting ssl.* from global scope");
2434 rc = HANDLER_ERROR;
2435 continue;
2436 }
2437 plugin_ssl_ctx * const s = p->ssl_ctxs + sidx;
2438 *s = *p->ssl_ctxs;/*(copy struct of ssl_ctx from global scope)*/
2439 continue;
2440 }
2441 /* PEM file is required */
2442 log_error(srv->errh, __FILE__, __LINE__,
2443 "ssl.pemfile has to be set when ssl.engine = \"enable\"");
2444 rc = HANDLER_ERROR;
2445 continue;
2446 }
2447
2448 /* configure ssl_ctx for socket */
2449
2450 /*conf.ssl_ctx = NULL;*//*(filled by network_init_ssl() even on error)*/
2451 if (0 == network_init_ssl(srv, &conf, p)) {
2452 plugin_ssl_ctx * const s = p->ssl_ctxs + sidx;
2453 s->ssl_ctx = conf.ssl_ctx;
2454 }
2455 else {
2456 SSL_CTX_free(conf.ssl_ctx);
2457 rc = HANDLER_ERROR;
2458 }
2459 }
2460
2461 #ifdef HAVE_SESSION_TICKET
2462 if (rc == HANDLER_GO_ON && ssl_is_init)
2463 mod_openssl_session_ticket_key_check(p, log_epoch_secs);
2464 #endif
2465
2466 free(srvplug.cvlist);
2467 return rc;
2468 }
2469
2470
SETDEFAULTS_FUNC(mod_openssl_set_defaults)2471 SETDEFAULTS_FUNC(mod_openssl_set_defaults)
2472 {
2473 static const config_plugin_keys_t cpk[] = {
2474 { CONST_STR_LEN("ssl.pemfile"),
2475 T_CONFIG_STRING,
2476 T_CONFIG_SCOPE_CONNECTION }
2477 ,{ CONST_STR_LEN("ssl.privkey"),
2478 T_CONFIG_STRING,
2479 T_CONFIG_SCOPE_CONNECTION }
2480 ,{ CONST_STR_LEN("ssl.ca-file"),
2481 T_CONFIG_STRING,
2482 T_CONFIG_SCOPE_CONNECTION }
2483 ,{ CONST_STR_LEN("ssl.ca-dn-file"),
2484 T_CONFIG_STRING,
2485 T_CONFIG_SCOPE_CONNECTION }
2486 ,{ CONST_STR_LEN("ssl.ca-crl-file"),
2487 T_CONFIG_STRING,
2488 T_CONFIG_SCOPE_CONNECTION }
2489 ,{ CONST_STR_LEN("ssl.read-ahead"),
2490 T_CONFIG_BOOL,
2491 T_CONFIG_SCOPE_CONNECTION }
2492 ,{ CONST_STR_LEN("ssl.disable-client-renegotiation"),
2493 T_CONFIG_BOOL, /*(directive ignored)*/
2494 T_CONFIG_SCOPE_CONNECTION }
2495 ,{ CONST_STR_LEN("ssl.verifyclient.activate"),
2496 T_CONFIG_BOOL,
2497 T_CONFIG_SCOPE_CONNECTION }
2498 ,{ CONST_STR_LEN("ssl.verifyclient.enforce"),
2499 T_CONFIG_BOOL,
2500 T_CONFIG_SCOPE_CONNECTION }
2501 ,{ CONST_STR_LEN("ssl.verifyclient.depth"),
2502 T_CONFIG_SHORT,
2503 T_CONFIG_SCOPE_CONNECTION }
2504 ,{ CONST_STR_LEN("ssl.verifyclient.username"),
2505 T_CONFIG_STRING,
2506 T_CONFIG_SCOPE_CONNECTION }
2507 ,{ CONST_STR_LEN("ssl.verifyclient.exportcert"),
2508 T_CONFIG_BOOL,
2509 T_CONFIG_SCOPE_CONNECTION }
2510 ,{ CONST_STR_LEN("ssl.acme-tls-1"),
2511 T_CONFIG_STRING,
2512 T_CONFIG_SCOPE_CONNECTION }
2513 ,{ CONST_STR_LEN("ssl.stapling-file"),
2514 T_CONFIG_STRING,
2515 T_CONFIG_SCOPE_CONNECTION }
2516 ,{ CONST_STR_LEN("debug.log-ssl-noise"),
2517 T_CONFIG_BOOL,
2518 T_CONFIG_SCOPE_CONNECTION }
2519 ,{ CONST_STR_LEN("ssl.verifyclient.ca-file"),
2520 T_CONFIG_STRING,
2521 T_CONFIG_SCOPE_CONNECTION }
2522 ,{ CONST_STR_LEN("ssl.verifyclient.ca-dn-file"),
2523 T_CONFIG_STRING,
2524 T_CONFIG_SCOPE_CONNECTION }
2525 ,{ CONST_STR_LEN("ssl.verifyclient.ca-crl-file"),
2526 T_CONFIG_STRING,
2527 T_CONFIG_SCOPE_CONNECTION }
2528 ,{ NULL, 0,
2529 T_CONFIG_UNSET,
2530 T_CONFIG_SCOPE_UNSET }
2531 };
2532
2533 plugin_data * const p = p_d;
2534 p->srv = srv;
2535 p->cafiles = array_init(0);
2536 if (!config_plugin_values_init(srv, p, cpk, "mod_openssl"))
2537 return HANDLER_ERROR;
2538
2539 const buffer *default_ssl_ca_crl_file = NULL;
2540
2541 /* process and validate config directives
2542 * (init i to 0 if global context; to 1 to skip empty global context) */
2543 for (int i = !p->cvlist[0].v.u2[1]; i < p->nconfig; ++i) {
2544 config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0];
2545 config_plugin_value_t *pemfile = NULL;
2546 config_plugin_value_t *privkey = NULL;
2547 const buffer *ssl_stapling_file = NULL;
2548 const buffer *ssl_ca_file = NULL;
2549 const buffer *ssl_ca_dn_file = NULL;
2550 const buffer *ssl_ca_crl_file = NULL;
2551 X509_STORE *ca_store = NULL;
2552 for (; -1 != cpv->k_id; ++cpv) {
2553 switch (cpv->k_id) {
2554 case 0: /* ssl.pemfile */
2555 if (!buffer_is_blank(cpv->v.b)) pemfile = cpv;
2556 break;
2557 case 1: /* ssl.privkey */
2558 if (!buffer_is_blank(cpv->v.b)) privkey = cpv;
2559 break;
2560 case 15:/* ssl.verifyclient.ca-file */
2561 cpv->k_id = 2;
2562 __attribute_fallthrough__
2563 case 2: /* ssl.ca-file */
2564 if (buffer_is_blank(cpv->v.b)) break;
2565 if (!mod_openssl_init_once_openssl(srv)) return HANDLER_ERROR;
2566 ssl_ca_file = cpv->v.b;
2567 cpv->v.v = mod_wolfssl_load_cacerts(ssl_ca_file, srv->errh);
2568 if (NULL != cpv->v.v) {
2569 cpv->vtype = T_CONFIG_LOCAL;
2570 ca_store = ((plugin_cacerts *)cpv->v.v)->certs;
2571 }
2572 else {
2573 log_error(srv->errh, __FILE__, __LINE__, "SSL: %s %s",
2574 ERR_error_string(ERR_get_error(), NULL),
2575 ssl_ca_file->ptr);
2576 return HANDLER_ERROR;
2577 }
2578 break;
2579 case 16:/* ssl.verifyclient.ca-dn-file */
2580 cpv->k_id = 3;
2581 __attribute_fallthrough__
2582 case 3: /* ssl.ca-dn-file */
2583 if (buffer_is_blank(cpv->v.b)) break;
2584 if (!mod_openssl_init_once_openssl(srv)) return HANDLER_ERROR;
2585 ssl_ca_dn_file = cpv->v.b;
2586 #ifndef OPENSSL_ALL
2587 {
2588 log_error(srv->errh, __FILE__, __LINE__,
2589 "SSL: You specified %s but wolfssl library built without "
2590 "necessary support", cpk[cpv->k_id].k);
2591 return HANDLER_ERROR;
2592 }
2593 #endif
2594 cpv->v.v = mod_wolfssl_load_client_CA_file(ssl_ca_dn_file,
2595 srv->errh);
2596 if (NULL != cpv->v.v) {
2597 cpv->vtype = T_CONFIG_LOCAL;
2598 }
2599 else {
2600 log_error(srv->errh, __FILE__, __LINE__, "SSL: %s %s",
2601 ERR_error_string(ERR_get_error(), NULL),
2602 ssl_ca_dn_file->ptr);
2603 return HANDLER_ERROR;
2604 }
2605 break;
2606 case 17:/* ssl.verifyclient.ca-crl-file */
2607 cpv->k_id = 4;
2608 __attribute_fallthrough__
2609 case 4: /* ssl.ca-crl-file */
2610 if (buffer_is_blank(cpv->v.b)) break;
2611 ssl_ca_crl_file = cpv->v.b;
2612 if (0 == i) default_ssl_ca_crl_file = cpv->v.b;
2613 break;
2614 case 5: /* ssl.read-ahead */
2615 case 6: /* ssl.disable-client-renegotiation */
2616 /*(ignored; unsafe renegotiation disabled by default)*/
2617 case 7: /* ssl.verifyclient.activate */
2618 case 8: /* ssl.verifyclient.enforce */
2619 break;
2620 case 9: /* ssl.verifyclient.depth */
2621 if (cpv->v.shrt > 255) {
2622 log_error(srv->errh, __FILE__, __LINE__,
2623 "%s is absurdly large (%hu); limiting to 255",
2624 cpk[cpv->k_id].k, cpv->v.shrt);
2625 cpv->v.shrt = 255;
2626 }
2627 break;
2628 case 10:/* ssl.verifyclient.username */
2629 if (buffer_is_blank(cpv->v.b))
2630 cpv->v.b = NULL;
2631 break;
2632 case 11:/* ssl.verifyclient.exportcert */
2633 break;
2634 case 12:/* ssl.acme-tls-1 */
2635 if (buffer_is_blank(cpv->v.b))
2636 cpv->v.b = NULL;
2637 break;
2638 case 13:/* ssl.stapling-file */
2639 if (!buffer_is_blank(cpv->v.b))
2640 ssl_stapling_file = cpv->v.b;
2641 break;
2642 case 14:/* debug.log-ssl-noise */
2643 #if 0 /*(handled further above)*/
2644 case 15:/* ssl.verifyclient.ca-file */
2645 case 16:/* ssl.verifyclient.ca-dn-file */
2646 case 17:/* ssl.verifyclient.ca-crl-file */
2647 #endif
2648 break;
2649 default:/* should not happen */
2650 break;
2651 }
2652 }
2653
2654 /* p->cafiles for legacy only */
2655 /* load all ssl.ca-files into a single chain */
2656 /*(certificate load order might matter)*/
2657 if (ssl_ca_dn_file)
2658 array_insert_value(p->cafiles, BUF_PTR_LEN(ssl_ca_dn_file));
2659 if (ssl_ca_file)
2660 array_insert_value(p->cafiles, BUF_PTR_LEN(ssl_ca_file));
2661 UNUSED(ca_store);
2662 UNUSED(ssl_ca_crl_file);
2663 UNUSED(default_ssl_ca_crl_file);
2664
2665 if (pemfile) {
2666 #ifndef HAVE_TLS_EXTENSIONS
2667 config_cond_info cfginfo;
2668 uint32_t j = (uint32_t)p->cvlist[i].k_id;
2669 config_get_config_cond_info(&cfginfo, j);
2670 if (j > 0 && (COMP_SERVER_SOCKET != cfginfo.comp
2671 || cfginfo.cond != CONFIG_COND_EQ)) {
2672 if (COMP_HTTP_HOST == cfginfo.comp)
2673 log_error(srv->errh, __FILE__, __LINE__, "SSL:"
2674 "can't use ssl.pemfile with $HTTP[\"host\"], "
2675 "as openssl version does not support TLS extensions");
2676 else
2677 log_error(srv->errh, __FILE__, __LINE__, "SSL:"
2678 "ssl.pemfile only works in SSL socket binding context "
2679 "as openssl version does not support TLS extensions");
2680 return HANDLER_ERROR;
2681 }
2682 #endif
2683 if (NULL == privkey) privkey = pemfile;
2684 pemfile->v.v =
2685 network_openssl_load_pemfile(srv, pemfile->v.b, privkey->v.b,
2686 ssl_stapling_file);
2687 if (pemfile->v.v)
2688 pemfile->vtype = T_CONFIG_LOCAL;
2689 else
2690 return HANDLER_ERROR;
2691 }
2692 }
2693
2694 p->defaults.ssl_verifyclient = 0;
2695 p->defaults.ssl_verifyclient_enforce = 1;
2696 p->defaults.ssl_verifyclient_depth = 9;
2697 p->defaults.ssl_verifyclient_export_cert = 0;
2698 p->defaults.ssl_read_ahead = 0;
2699
2700 /* initialize p->defaults from global config context */
2701 if (p->nconfig > 0 && p->cvlist->v.u2[1]) {
2702 const config_plugin_value_t *cpv = p->cvlist + p->cvlist->v.u2[0];
2703 if (-1 != cpv->k_id)
2704 mod_openssl_merge_config(&p->defaults, cpv);
2705 }
2706
2707 return mod_openssl_set_defaults_sockets(srv, p);
2708 }
2709
2710
2711 /* local_send_buffer is a static buffer of size (LOCAL_SEND_BUFSIZE)
2712 *
2713 * it has to stay at the same location all the time to satisfy the needs
2714 * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE
2715 *
2716 * buffer is allocated once, is NOT realloced (note: not thread-safe)
2717 *
2718 * (Note: above restriction no longer true since SSL_CTX_set_mode() is
2719 * called with SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)
2720 * */
2721
2722 /* copy small mem chunks into single large buffer before SSL_write()
2723 * to reduce number times write() called underneath SSL_write() and
2724 * potentially reduce number of packets generated if TCP_NODELAY */
2725
2726
2727 static int
2728 mod_openssl_close_notify(handler_ctx *hctx);
2729
2730
2731 static int
connection_write_cq_ssl(connection * const con,chunkqueue * const cq,off_t max_bytes)2732 connection_write_cq_ssl (connection * const con, chunkqueue * const cq, off_t max_bytes)
2733 {
2734 handler_ctx * const hctx = con->plugin_ctx[plugin_data_singleton->id];
2735 SSL * const ssl = hctx->ssl;
2736 log_error_st * const errh = hctx->errh;
2737
2738 if (__builtin_expect( (0 != hctx->close_notify), 0))
2739 return mod_openssl_close_notify(hctx);
2740
2741 while (max_bytes > 0 && !chunkqueue_is_empty(cq)) {
2742 char *data = local_send_buffer;
2743 uint32_t data_len = LOCAL_SEND_BUFSIZE < max_bytes
2744 ? LOCAL_SEND_BUFSIZE
2745 : (uint32_t)max_bytes;
2746 int wr;
2747
2748 if (0 != chunkqueue_peek_data(cq, &data, &data_len, errh)) return -1;
2749 if (__builtin_expect( (0 == data_len), 0)) {
2750 chunkqueue_remove_finished_chunks(cq);
2751 continue;
2752 }
2753
2754 /**
2755 * SSL_write man-page
2756 *
2757 * WARNING
2758 * When an SSL_write() operation has to be repeated because of
2759 * SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be
2760 * repeated with the same arguments.
2761 */
2762
2763 ERR_clear_error();
2764 wr = SSL_write(ssl, data, data_len);
2765
2766 if (__builtin_expect( (hctx->renegotiations > 1), 0)) {
2767 log_error(errh, __FILE__, __LINE__,
2768 "SSL: renegotiation initiated by client, killing connection");
2769 return -1;
2770 }
2771
2772 if (wr <= 0) {
2773 int ssl_r;
2774 unsigned long err;
2775
2776 switch ((ssl_r = SSL_get_error(ssl, wr))) {
2777 case SSL_ERROR_WANT_READ:
2778 con->is_readable = -1;
2779 return 0; /* try again later */
2780 case SSL_ERROR_WANT_WRITE:
2781 con->is_writable = -1;
2782 return 0; /* try again later */
2783 case SSL_ERROR_SYSCALL:
2784 /* perhaps we have error waiting in our error-queue */
2785 if (0 != (err = ERR_get_error())) {
2786 do {
2787 log_error(errh, __FILE__, __LINE__,
2788 "SSL: %d %d %s",ssl_r,wr,ERR_error_string(err,NULL));
2789 } while((err = ERR_get_error()));
2790 } else if (wr == -1) {
2791 /* no, but we have errno */
2792 switch(errno) {
2793 case EPIPE:
2794 case ECONNRESET:
2795 return -2;
2796 default:
2797 log_perror(errh, __FILE__, __LINE__,
2798 "SSL: %d %d", ssl_r, wr);
2799 break;
2800 }
2801 } else {
2802 /* neither error-queue nor errno ? */
2803 log_perror(errh, __FILE__, __LINE__,
2804 "SSL (error): %d %d", ssl_r, wr);
2805 }
2806 break;
2807
2808 case SSL_ERROR_ZERO_RETURN:
2809 /* clean shutdown on the remote side */
2810
2811 if (wr == 0) return -2;
2812
2813 __attribute_fallthrough__
2814 default:
2815 while((err = ERR_get_error())) {
2816 log_error(errh, __FILE__, __LINE__,
2817 "SSL: %d %d %s", ssl_r, wr, ERR_error_string(err, NULL));
2818 }
2819 break;
2820 }
2821 return -1;
2822 }
2823
2824 chunkqueue_mark_written(cq, wr);
2825 max_bytes -= wr;
2826
2827 if ((size_t) wr < data_len) break; /* try again later */
2828 }
2829
2830 return 0;
2831 }
2832
2833
2834 static int
connection_read_cq_ssl(connection * const con,chunkqueue * const cq,off_t max_bytes)2835 connection_read_cq_ssl (connection * const con, chunkqueue * const cq, off_t max_bytes)
2836 {
2837 handler_ctx * const hctx = con->plugin_ctx[plugin_data_singleton->id];
2838 int len;
2839 char *mem = NULL;
2840 size_t mem_len = 0;
2841
2842 UNUSED(max_bytes);
2843
2844 if (__builtin_expect( (0 != hctx->close_notify), 0))
2845 return mod_openssl_close_notify(hctx);
2846
2847 ERR_clear_error();
2848 do {
2849 len = SSL_pending(hctx->ssl);
2850 mem_len = len < 2048 ? 2048 : (size_t)len;
2851 chunk * const ckpt = cq->last;
2852 mem = chunkqueue_get_memory(cq, &mem_len);
2853
2854 len = SSL_read(hctx->ssl, mem, mem_len);
2855 chunkqueue_use_memory(cq, ckpt, len > 0 ? len : 0);
2856
2857 if (hctx->renegotiations > 1) {
2858 log_error(hctx->errh, __FILE__, __LINE__,
2859 "SSL: renegotiation initiated by client, killing connection");
2860 return -1;
2861 }
2862
2863 #ifdef HAVE_ALPN
2864 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
2865 if (hctx->alpn) {
2866 if (hctx->alpn == MOD_OPENSSL_ALPN_H2) {
2867 if (0 != mod_openssl_alpn_h2_policy(hctx))
2868 return -1;
2869 }
2870 else if (hctx->alpn == MOD_OPENSSL_ALPN_ACME_TLS_1) {
2871 chunkqueue_reset(cq);
2872 /* initiate handshake in order to send ServerHello.
2873 * Once TLS handshake is complete, return -1 to result in
2874 * CON_STATE_ERROR so that socket connection is quickly closed*/
2875 if (1 == SSL_do_handshake(hctx->ssl)) return -1;
2876 len = -1;
2877 break;
2878 }
2879 hctx->alpn = 0;
2880 }
2881 #endif
2882 #endif
2883 } while (len > 0
2884 && (hctx->conf.ssl_read_ahead || SSL_pending(hctx->ssl) > 0));
2885
2886 if (len < 0) {
2887 int oerrno = errno;
2888 int rc, ssl_err;
2889 switch ((rc = SSL_get_error(hctx->ssl, len))) {
2890 case SSL_ERROR_WANT_WRITE:
2891 con->is_writable = -1;
2892 __attribute_fallthrough__
2893 case SSL_ERROR_WANT_READ:
2894 con->is_readable = 0;
2895
2896 /* the manual says we have to call SSL_read with the same arguments
2897 * next time. we ignore this restriction; no one has complained
2898 * about it in 1.5 yet, so it probably works anyway.
2899 */
2900
2901 return 0;
2902 case SSL_ERROR_SYSCALL:
2903 /**
2904 * man SSL_get_error()
2905 *
2906 * SSL_ERROR_SYSCALL
2907 * Some I/O error occurred. The OpenSSL error queue may contain
2908 * more information on the error. If the error queue is empty
2909 * (i.e. ERR_get_error() returns 0), ret can be used to find out
2910 * more about the error: If ret == 0, an EOF was observed that
2911 * violates the protocol. If ret == -1, the underlying BIO
2912 * reported an I/O error (for socket I/O on Unix systems, consult
2913 * errno for details).
2914 *
2915 */
2916 while((ssl_err = ERR_get_error())) {
2917 /* get all errors from the error-queue */
2918 log_error(hctx->errh, __FILE__, __LINE__,
2919 "SSL: %d %s", rc, ERR_error_string(ssl_err, NULL));
2920 }
2921
2922 switch(oerrno) {
2923 case ECONNRESET:
2924 if (!hctx->conf.ssl_log_noise) break;
2925 __attribute_fallthrough__
2926 default:
2927 /* (oerrno should be something like ECONNABORTED not 0
2928 * if client disconnected before anything was sent
2929 * (e.g. TCP connection probe), but it does not appear
2930 * that openssl provides such notification, not even
2931 * something like SSL_R_SSL_HANDSHAKE_FAILURE) */
2932 if (0==oerrno && 0==cq->bytes_in && !hctx->conf.ssl_log_noise)
2933 break;
2934
2935 errno = oerrno; /*(for log_perror())*/
2936 log_perror(hctx->errh, __FILE__, __LINE__,
2937 "SSL: %d %d %d", len, rc, oerrno);
2938 break;
2939 }
2940
2941 break;
2942 case SSL_ERROR_ZERO_RETURN:
2943 /* clean shutdown on the remote side */
2944
2945 /* future: might set flag to record that we received CLOSE_NOTIFY
2946 * TLS alert from peer, then have future calls to this func return
2947 * the equivalent of EOF, but we also want to remove read interest
2948 * on fd, perhaps by setting RDHUP. If setting is_readable, ensure
2949 * that callers avoid spinning if we return EOF while is_readable.
2950 *
2951 * Should we treat this like len == 0 below and return -2 ? */
2952
2953 /*__attribute_fallthrough__*/
2954 default:
2955 while((ssl_err = ERR_get_error())) {
2956 switch (ERR_GET_REASON(ssl_err)) {
2957 case SSL_R_SSL_HANDSHAKE_FAILURE:
2958 #ifdef SSL_R_UNEXPECTED_EOF_WHILE_READING
2959 case SSL_R_UNEXPECTED_EOF_WHILE_READING:
2960 #endif
2961 #ifdef SSL_R_TLSV1_ALERT_UNKNOWN_CA
2962 case SSL_R_TLSV1_ALERT_UNKNOWN_CA:
2963 #endif
2964 #ifdef SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN
2965 case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:
2966 #endif
2967 #ifdef SSL_R_SSLV3_ALERT_BAD_CERTIFICATE
2968 case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:
2969 #endif
2970 if (!hctx->conf.ssl_log_noise) continue;
2971 break;
2972 default:
2973 break;
2974 }
2975 /* get all errors from the error-queue */
2976 log_error(hctx->errh, __FILE__, __LINE__,
2977 "SSL: %d %s", rc, ERR_error_string(ssl_err, NULL));
2978 }
2979 break;
2980 }
2981 return -1;
2982 } else if (len == 0) {
2983 con->is_readable = 0;
2984 /* the other end close the connection -> KEEP-ALIVE */
2985
2986 return -2;
2987 } else {
2988 return 0;
2989 }
2990 }
2991
2992
CONNECTION_FUNC(mod_openssl_handle_con_accept)2993 CONNECTION_FUNC(mod_openssl_handle_con_accept)
2994 {
2995 const server_socket *srv_sock = con->srv_socket;
2996 if (!srv_sock->is_ssl) return HANDLER_GO_ON;
2997
2998 plugin_data *p = p_d;
2999 handler_ctx * const hctx = handler_ctx_init();
3000 request_st * const r = &con->request;
3001 hctx->r = r;
3002 hctx->con = con;
3003 hctx->tmp_buf = con->srv->tmp_buf;
3004 hctx->errh = r->conf.errh;
3005 con->plugin_ctx[p->id] = hctx;
3006 buffer_blank(&r->uri.authority);
3007
3008 plugin_ssl_ctx * const s = p->ssl_ctxs + srv_sock->sidx;
3009 hctx->ssl = SSL_new(s->ssl_ctx);
3010 if (NULL != hctx->ssl
3011 && SSL_set_app_data(hctx->ssl, hctx)
3012 && SSL_set_fd(hctx->ssl, con->fd)) {
3013 SSL_set_accept_state(hctx->ssl);
3014 con->network_read = connection_read_cq_ssl;
3015 con->network_write = connection_write_cq_ssl;
3016 con->proto_default_port = 443; /* "https" */
3017 mod_openssl_patch_config(r, &hctx->conf);
3018 return HANDLER_GO_ON;
3019 }
3020 else {
3021 log_error(r->conf.errh, __FILE__, __LINE__,
3022 "SSL: %s", ERR_error_string(ERR_get_error(), NULL));
3023 return HANDLER_ERROR;
3024 }
3025 }
3026
3027
3028 static void
mod_openssl_detach(handler_ctx * hctx)3029 mod_openssl_detach(handler_ctx *hctx)
3030 {
3031 /* step aside from further SSL processing
3032 * (used after handle_connection_shut_wr hook) */
3033 /* future: might restore prior network_read and network_write fn ptrs */
3034 hctx->con->is_ssl_sock = 0;
3035 /* if called after handle_connection_shut_wr hook, shutdown SHUT_WR */
3036 if (-1 == hctx->close_notify) shutdown(hctx->con->fd, SHUT_WR);
3037 hctx->close_notify = 1;
3038 }
3039
3040
CONNECTION_FUNC(mod_openssl_handle_con_shut_wr)3041 CONNECTION_FUNC(mod_openssl_handle_con_shut_wr)
3042 {
3043 plugin_data *p = p_d;
3044 handler_ctx *hctx = con->plugin_ctx[p->id];
3045 if (NULL == hctx) return HANDLER_GO_ON;
3046
3047 hctx->close_notify = -2;
3048 if (SSL_is_init_finished(hctx->ssl)) {
3049 mod_openssl_close_notify(hctx);
3050 }
3051 else {
3052 mod_openssl_detach(hctx);
3053 }
3054
3055 return HANDLER_GO_ON;
3056 }
3057
3058
3059 static int
mod_openssl_close_notify(handler_ctx * hctx)3060 mod_openssl_close_notify(handler_ctx *hctx)
3061 {
3062 int ret, ssl_r;
3063 unsigned long err;
3064 log_error_st *errh;
3065
3066 if (1 == hctx->close_notify) return -2;
3067
3068 ERR_clear_error();
3069 switch ((ret = SSL_shutdown(hctx->ssl))) {
3070 case 1:
3071 mod_openssl_detach(hctx);
3072 return -2;
3073 case 0:
3074 /* Drain SSL read buffers in case pending records need processing.
3075 * Limit to reading next record to avoid denial of service when CPU
3076 * processing TLS is slower than arrival speed of TLS data packets.
3077 * (unless hctx->conf.ssl_read_ahead is set)
3078 *
3079 * references:
3080 *
3081 * "New session ticket breaks bidirectional shutdown of TLS 1.3 connection"
3082 * https://github.com/openssl/openssl/issues/6262
3083 *
3084 * The peer is still allowed to send data after receiving the
3085 * "close notify" event. If the peer did send data it need to be
3086 * processed by calling SSL_read() before calling SSL_shutdown() a
3087 * second time. SSL_read() will indicate the end of the peer data by
3088 * returning <= 0 and SSL_get_error() returning
3089 * SSL_ERROR_ZERO_RETURN. It is recommended to call SSL_read()
3090 * between SSL_shutdown() calls.
3091 *
3092 * Additional discussion in "Auto retry in shutdown"
3093 * https://github.com/openssl/openssl/pull/6340
3094 */
3095 ssl_r = SSL_pending(hctx->ssl);
3096 if (ssl_r) {
3097 do {
3098 char buf[4096];
3099 ret = SSL_read(hctx->ssl, buf, (int)sizeof(buf));
3100 } while (ret > 0 && (hctx->conf.ssl_read_ahead||(ssl_r-=ret)));
3101 }
3102
3103 ERR_clear_error();
3104 switch ((ret = SSL_shutdown(hctx->ssl))) {
3105 case 1:
3106 mod_openssl_detach(hctx);
3107 return -2;
3108 case 0:
3109 hctx->close_notify = -1;
3110 return 0;
3111 default:
3112 break;
3113 }
3114
3115 __attribute_fallthrough__
3116 default:
3117
3118 if (!SSL_is_init_finished(hctx->ssl)) {
3119 mod_openssl_detach(hctx);
3120 return -2;
3121 }
3122
3123 switch ((ssl_r = SSL_get_error(hctx->ssl, ret))) {
3124 case SSL_ERROR_WANT_WRITE:
3125 case SSL_ERROR_WANT_READ:
3126 case SSL_ERROR_ZERO_RETURN: /*(unexpected here)*/
3127 hctx->close_notify = -1;
3128 return 0; /* try again later */
3129 case SSL_ERROR_SYSCALL:
3130 if (0 == ERR_peek_error()) {
3131 switch(errno) {
3132 case 0: /*ssl bug (see lighttpd ticket #2213)*/
3133 case EPIPE:
3134 case ECONNRESET:
3135 mod_openssl_detach(hctx);
3136 return -2;
3137 default:
3138 log_perror(hctx->r->conf.errh, __FILE__, __LINE__,
3139 "SSL (error): %d %d", ssl_r, ret);
3140 break;
3141 }
3142 break;
3143 }
3144 __attribute_fallthrough__
3145 default:
3146 errh = hctx->r->conf.errh;
3147 while((err = ERR_get_error())) {
3148 log_error(errh, __FILE__, __LINE__,
3149 "SSL: %d %d %s", ssl_r, ret, ERR_error_string(err, NULL));
3150 }
3151
3152 break;
3153 }
3154 }
3155 ERR_clear_error();
3156 hctx->close_notify = -1;
3157 return ret;
3158 }
3159
3160
CONNECTION_FUNC(mod_openssl_handle_con_close)3161 CONNECTION_FUNC(mod_openssl_handle_con_close)
3162 {
3163 plugin_data *p = p_d;
3164 handler_ctx *hctx = con->plugin_ctx[p->id];
3165 if (NULL != hctx) {
3166 con->plugin_ctx[p->id] = NULL;
3167 handler_ctx_free(hctx);
3168 }
3169
3170 return HANDLER_GO_ON;
3171 }
3172
3173
3174 #ifndef OBJ_nid2sn
3175 #define OBJ_nid2sn wolfSSL_OBJ_nid2sn
3176 #endif
3177 #ifndef OBJ_obj2nid
3178 #define OBJ_obj2nid wolfSSL_OBJ_obj2nid
3179 #endif
3180 #include <wolfssl/wolfcrypt/asn_public.h>
3181
3182
3183 static void
https_add_ssl_client_subject(request_st * const r,X509_NAME * xn)3184 https_add_ssl_client_subject (request_st * const r, X509_NAME *xn)
3185 {
3186 const size_t prelen = sizeof("SSL_CLIENT_S_DN_")-1;
3187 char key[64] = "SSL_CLIENT_S_DN_";
3188 for (int i = 0, nentries = X509_NAME_entry_count(xn); i < nentries; ++i) {
3189 int xobjnid;
3190 const char * xobjsn;
3191 X509_NAME_ENTRY *xe;
3192
3193 if (!(xe = wolfSSL_X509_NAME_get_entry(xn, i))) {
3194 continue;
3195 }
3196 xobjnid = OBJ_obj2nid((ASN1_OBJECT*)X509_NAME_ENTRY_get_object(xe));
3197 xobjsn = OBJ_nid2sn(xobjnid);
3198 if (xobjsn) {
3199 const size_t len = strlen(xobjsn);
3200 if (prelen+len >= sizeof(key)) continue;
3201 memcpy(key+prelen, xobjsn, len); /*(not '\0'-terminated)*/
3202 http_header_env_set(r, key, prelen+len,
3203 (const char*)X509_NAME_ENTRY_get_data(xe)->data,
3204 X509_NAME_ENTRY_get_data(xe)->length);
3205 }
3206 }
3207 }
3208
3209
3210 __attribute_cold__
3211 static void
https_add_ssl_client_verify_err(buffer * const b,long status)3212 https_add_ssl_client_verify_err (buffer * const b, long status)
3213 {
3214 char errstr[256];
3215 ERR_error_string_n(status, errstr, sizeof(errstr));
3216 buffer_append_string(b, errstr);
3217 }
3218
3219
3220 __attribute_noinline__
3221 static void
https_add_ssl_client_entries(request_st * const r,handler_ctx * const hctx)3222 https_add_ssl_client_entries (request_st * const r, handler_ctx * const hctx)
3223 {
3224 X509 *xs;
3225 X509_NAME *xn;
3226 buffer *vb = http_header_env_set_ptr(r, CONST_STR_LEN("SSL_CLIENT_VERIFY"));
3227
3228 long vr = SSL_get_verify_result(hctx->ssl);
3229 if (vr != X509_V_OK) {
3230 buffer_copy_string_len(vb, CONST_STR_LEN("FAILED:"));
3231 https_add_ssl_client_verify_err(vb, vr);
3232 return;
3233 } else if (!(xs = SSL_get_peer_certificate(hctx->ssl))) {
3234 buffer_copy_string_len(vb, CONST_STR_LEN("NONE"));
3235 return;
3236 } else {
3237 buffer_copy_string_len(vb, CONST_STR_LEN("SUCCESS"));
3238 }
3239
3240 xn = X509_get_subject_name(xs);
3241 {
3242 char buf[256];
3243 int len = safer_X509_NAME_oneline(xn, buf, sizeof(buf));
3244 if (len > 0) {
3245 if (len >= (int)sizeof(buf)) len = (int)sizeof(buf)-1;
3246 http_header_env_set(r,
3247 CONST_STR_LEN("SSL_CLIENT_S_DN"),
3248 buf, (size_t)len);
3249 }
3250 }
3251
3252 https_add_ssl_client_subject(r, xn);
3253
3254 {
3255 byte buf[64];
3256 int bsz = (int)sizeof(buf);
3257 if (wolfSSL_X509_get_serial_number(xs, buf, &bsz) == WOLFSSL_SUCCESS) {
3258 buffer_append_string_encoded_hex_uc(
3259 http_header_env_set_ptr(r, CONST_STR_LEN("SSL_CLIENT_M_SERIAL")),
3260 (char *)buf, (size_t)bsz);
3261 }
3262 }
3263
3264 if (hctx->conf.ssl_verifyclient_username) {
3265 /* pick one of the exported values as "REMOTE_USER", for example
3266 * ssl.verifyclient.username = "SSL_CLIENT_S_DN_UID"
3267 * or
3268 * ssl.verifyclient.username = "SSL_CLIENT_S_DN_emailAddress"
3269 */
3270 const buffer *varname = hctx->conf.ssl_verifyclient_username;
3271 vb = http_header_env_get(r, BUF_PTR_LEN(varname));
3272 if (vb) { /* same as mod_auth_api.c:http_auth_setenv() */
3273 http_header_env_set(r,
3274 CONST_STR_LEN("REMOTE_USER"),
3275 BUF_PTR_LEN(vb));
3276 http_header_env_set(r,
3277 CONST_STR_LEN("AUTH_TYPE"),
3278 CONST_STR_LEN("SSL_CLIENT_VERIFY"));
3279 }
3280 }
3281
3282 if (hctx->conf.ssl_verifyclient_export_cert) {
3283 int dersz, pemsz;
3284 const unsigned char *der = wolfSSL_X509_get_der(xs, &dersz);
3285 pemsz = der ? wc_DerToPemEx(der, dersz, NULL, 0, NULL, CERT_TYPE) : 0;
3286 if (pemsz > 0) {
3287 vb = http_header_env_set_ptr(r, CONST_STR_LEN("SSL_CLIENT_CERT"));
3288 if (0 == wc_DerToPemEx(der, dersz,
3289 (byte *)buffer_string_prepare_copy(vb,pemsz),
3290 pemsz, NULL, CERT_TYPE))
3291 buffer_commit(vb, (uint32_t)pemsz);
3292 }
3293 }
3294 X509_free(xs);
3295 }
3296
3297
3298 static void
http_cgi_ssl_env(request_st * const r,handler_ctx * const hctx)3299 http_cgi_ssl_env (request_st * const r, handler_ctx * const hctx)
3300 {
3301 const char *s;
3302 const SSL_CIPHER *cipher;
3303
3304 s = SSL_get_version(hctx->ssl);
3305 http_header_env_set(r, CONST_STR_LEN("SSL_PROTOCOL"), s, strlen(s));
3306
3307 if ((cipher = SSL_get_current_cipher(hctx->ssl))) {
3308 s = SSL_CIPHER_get_name(cipher);
3309 http_header_env_set(r, CONST_STR_LEN("SSL_CIPHER"), s, strlen(s));
3310 /*(wolfSSL preprocessor defines are obnoxious)*/
3311 #if defined(OPENSSL_ALL) \
3312 || (defined(OPENSSL_EXTRA) \
3313 && (defined(HAVE_STUNNEL) || \
3314 defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \
3315 defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH)))
3316 int usekeysize, algkeysize = 0;
3317 char buf[LI_ITOSTRING_LENGTH];
3318 usekeysize = wolfSSL_CIPHER_get_bits(cipher, &algkeysize);
3319 if (0 == algkeysize) algkeysize = usekeysize;
3320 http_header_env_set(r, CONST_STR_LEN("SSL_CIPHER_USEKEYSIZE"),
3321 buf, li_itostrn(buf, sizeof(buf), usekeysize));
3322 http_header_env_set(r, CONST_STR_LEN("SSL_CIPHER_ALGKEYSIZE"),
3323 buf, li_itostrn(buf, sizeof(buf), algkeysize));
3324 #endif
3325 }
3326 }
3327
3328
REQUEST_FUNC(mod_openssl_handle_request_env)3329 REQUEST_FUNC(mod_openssl_handle_request_env)
3330 {
3331 plugin_data *p = p_d;
3332 /* simple flag for request_env_patched */
3333 if (r->plugin_ctx[p->id]) return HANDLER_GO_ON;
3334 handler_ctx *hctx = r->con->plugin_ctx[p->id];
3335 if (NULL == hctx) return HANDLER_GO_ON;
3336 r->plugin_ctx[p->id] = (void *)(uintptr_t)1u;
3337
3338 http_cgi_ssl_env(r, hctx);
3339 if (hctx->conf.ssl_verifyclient) {
3340 https_add_ssl_client_entries(r, hctx);
3341 }
3342
3343 return HANDLER_GO_ON;
3344 }
3345
3346
REQUEST_FUNC(mod_openssl_handle_uri_raw)3347 REQUEST_FUNC(mod_openssl_handle_uri_raw)
3348 {
3349 /* mod_openssl must be loaded prior to mod_auth
3350 * if mod_openssl is configured to set REMOTE_USER based on client cert */
3351 /* mod_openssl must be loaded after mod_extforward
3352 * if mod_openssl config is based on lighttpd.conf remote IP conditional
3353 * using remote IP address set by mod_extforward, *unless* PROXY protocol
3354 * is enabled with extforward.hap-PROXY = "enable", in which case the
3355 * reverse is true: mod_extforward must be loaded after mod_openssl */
3356 plugin_data *p = p_d;
3357 handler_ctx *hctx = r->con->plugin_ctx[p->id];
3358 if (NULL == hctx) return HANDLER_GO_ON;
3359
3360 mod_openssl_patch_config(r, &hctx->conf);
3361 if (hctx->conf.ssl_verifyclient) {
3362 mod_openssl_handle_request_env(r, p);
3363 }
3364
3365 return HANDLER_GO_ON;
3366 }
3367
3368
REQUEST_FUNC(mod_openssl_handle_request_reset)3369 REQUEST_FUNC(mod_openssl_handle_request_reset)
3370 {
3371 plugin_data *p = p_d;
3372 r->plugin_ctx[p->id] = NULL; /* simple flag for request_env_patched */
3373 return HANDLER_GO_ON;
3374 }
3375
3376
TRIGGER_FUNC(mod_openssl_handle_trigger)3377 TRIGGER_FUNC(mod_openssl_handle_trigger) {
3378 const plugin_data * const p = p_d;
3379 const unix_time64_t cur_ts = log_epoch_secs;
3380 if (cur_ts & 0x3f) return HANDLER_GO_ON; /*(continue once each 64 sec)*/
3381 UNUSED(srv);
3382 UNUSED(p);
3383
3384 #ifdef HAVE_SESSION_TICKET
3385 mod_openssl_session_ticket_key_check(p, cur_ts);
3386 #endif
3387
3388 #ifdef HAVE_OCSP
3389 mod_openssl_refresh_stapling_files(srv, p, cur_ts);
3390 #endif
3391
3392 return HANDLER_GO_ON;
3393 }
3394
3395
3396 __attribute_cold__
3397 int mod_wolfssl_plugin_init (plugin *p);
mod_wolfssl_plugin_init(plugin * p)3398 int mod_wolfssl_plugin_init (plugin *p)
3399 {
3400 p->version = LIGHTTPD_VERSION_ID;
3401 p->name = "wolfssl";
3402 p->init = mod_openssl_init;
3403 p->cleanup = mod_openssl_free;
3404 p->priv_defaults= mod_openssl_set_defaults;
3405
3406 p->handle_connection_accept = mod_openssl_handle_con_accept;
3407 p->handle_connection_shut_wr = mod_openssl_handle_con_shut_wr;
3408 p->handle_connection_close = mod_openssl_handle_con_close;
3409 p->handle_uri_raw = mod_openssl_handle_uri_raw;
3410 p->handle_request_env = mod_openssl_handle_request_env;
3411 p->handle_request_reset = mod_openssl_handle_request_reset;
3412 p->handle_trigger = mod_openssl_handle_trigger;
3413
3414 return 0;
3415 }
3416
3417
3418 static int
mod_openssl_ssl_conf_proto_val(server * srv,const buffer * b,int max)3419 mod_openssl_ssl_conf_proto_val (server *srv, const buffer *b, int max)
3420 {
3421 if (NULL == b) /* default: min TLSv1.2, max TLSv1.3 */
3422 return max ? WOLFSSL_TLSV1_3 : WOLFSSL_TLSV1_2;
3423 else if (buffer_eq_icase_slen(b, CONST_STR_LEN("None"))) /*"disable" limit*/
3424 return max ? WOLFSSL_TLSV1_3 : WOLFSSL_TLSV1;
3425 else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.0")))
3426 return WOLFSSL_TLSV1;
3427 else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.1")))
3428 return WOLFSSL_TLSV1_1;
3429 else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.2")))
3430 return WOLFSSL_TLSV1_2;
3431 else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.3")))
3432 return WOLFSSL_TLSV1_3;
3433 else {
3434 if (buffer_eq_icase_slen(b, CONST_STR_LEN("DTLSv1"))
3435 || buffer_eq_icase_slen(b, CONST_STR_LEN("DTLSv1.2")))
3436 log_error(srv->errh, __FILE__, __LINE__,
3437 "SSL: ssl.openssl.ssl-conf-cmd %s %s ignored",
3438 max ? "MaxProtocol" : "MinProtocol", b->ptr);
3439 else
3440 log_error(srv->errh, __FILE__, __LINE__,
3441 "SSL: ssl.openssl.ssl-conf-cmd %s %s invalid; ignored",
3442 max ? "MaxProtocol" : "MinProtocol", b->ptr);
3443 }
3444 return max ? WOLFSSL_TLSV1_3 : WOLFSSL_TLSV1_2;
3445 }
3446
3447
3448 static int
mod_openssl_ssl_conf_cmd(server * srv,plugin_config_socket * s)3449 mod_openssl_ssl_conf_cmd (server *srv, plugin_config_socket *s)
3450 {
3451 /* reference:
3452 * https://www.openssl.org/docs/man1.1.1/man3/SSL_CONF_cmd.html */
3453 int rc = 0;
3454 buffer *cipherstring = NULL;
3455 /*buffer *ciphersuites = NULL;*/
3456 buffer *minb = NULL;
3457 buffer *maxb = NULL;
3458 buffer *curves = NULL;
3459
3460 for (size_t i = 0; i < s->ssl_conf_cmd->used; ++i) {
3461 data_string *ds = (data_string *)s->ssl_conf_cmd->data[i];
3462 if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("CipherString")))
3463 cipherstring = &ds->value;
3464 #if 0
3465 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Ciphersuites")))
3466 ciphersuites = &ds->value;
3467 #endif
3468 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Curves"))
3469 || buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Groups")))
3470 curves = &ds->value;
3471 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("DHParameters"))){
3472 if (!buffer_is_blank(&ds->value)) {
3473 if (!mod_openssl_ssl_conf_dhparameters(srv, s, &ds->value))
3474 rc = -1;
3475 }
3476 }
3477 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("MaxProtocol")))
3478 maxb = &ds->value;
3479 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("MinProtocol")))
3480 minb = &ds->value;
3481 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Protocol"))) {
3482 /* openssl config for Protocol=... is complex and deprecated */
3483 log_error(srv->errh, __FILE__, __LINE__,
3484 "SSL: ssl.openssl.ssl-conf-cmd %s ignored; "
3485 "use MinProtocol=... and MaxProtocol=... instead",
3486 ds->key.ptr);
3487 }
3488 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Options"))) {
3489 for (char *v = ds->value.ptr, *e; *v; v = e) {
3490 while (*v == ' ' || *v == '\t' || *v == ',') ++v;
3491 int flag = 1;
3492 if (*v == '-') {
3493 flag = 0;
3494 ++v;
3495 }
3496 else if (*v == '+')
3497 ++v;
3498 for (e = v; light_isalpha(*e); ++e) ;
3499 switch ((int)(e-v)) {
3500 case 11:
3501 if (buffer_eq_icase_ssn(v, "Compression", 11)) {
3502 /* (force disabled, the default, if HTTP/2 enabled) */
3503 if (srv->srvconf.h2proto)
3504 flag = 0;
3505 if (flag)
3506 SSL_CTX_clear_options(s->ssl_ctx,
3507 SSL_OP_NO_COMPRESSION);
3508 else
3509 SSL_CTX_set_options(s->ssl_ctx,
3510 SSL_OP_NO_COMPRESSION);
3511 continue;
3512 }
3513 break;
3514 case 13:
3515 if (buffer_eq_icase_ssn(v, "SessionTicket", 13)) {
3516 if (flag)
3517 SSL_CTX_clear_options(s->ssl_ctx,
3518 SSL_OP_NO_TICKET);
3519 else
3520 SSL_CTX_set_options(s->ssl_ctx,
3521 SSL_OP_NO_TICKET);
3522 continue;
3523 }
3524 break;
3525 case 16:
3526 if (buffer_eq_icase_ssn(v, "ServerPreference", 16)) {
3527 if (flag)
3528 SSL_CTX_set_options(s->ssl_ctx,
3529 SSL_OP_CIPHER_SERVER_PREFERENCE);
3530 else
3531 SSL_CTX_clear_options(s->ssl_ctx,
3532 SSL_OP_CIPHER_SERVER_PREFERENCE);
3533 s->ssl_honor_cipher_order = flag;
3534 continue;
3535 }
3536 break;
3537 default:
3538 break;
3539 }
3540 /* warn if not explicitly handled or ignored above */
3541 if (!flag) --v;
3542 log_error(srv->errh, __FILE__, __LINE__,
3543 "SSL: ssl.openssl.ssl-conf-cmd Options %.*s "
3544 "ignored", (int)(e-v), v);
3545 }
3546 }
3547 #if 0
3548 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("..."))) {
3549 }
3550 #endif
3551 else {
3552 /* warn if not explicitly handled or ignored above */
3553 log_error(srv->errh, __FILE__, __LINE__,
3554 "SSL: ssl.openssl.ssl-conf-cmd %s ignored",
3555 ds->key.ptr);
3556 }
3557
3558 }
3559
3560 if (minb) {
3561 int n = mod_openssl_ssl_conf_proto_val(srv, minb, 0);
3562 if (wolfSSL_CTX_SetMinVersion(s->ssl_ctx, n) != WOLFSSL_SUCCESS)
3563 rc = -1;
3564 }
3565
3566 if (maxb) {
3567 /* WolfSSL max ver is set at WolfSSL compile-time */
3568 #if LIBWOLFSSL_VERSION_HEX >= 0x04002000
3569 /*(could use SSL_OP_NO_* before 4.2.0)*/
3570 /*(wolfSSL_CTX_set_max_proto_version() 4.6.0 uses different defines)*/
3571 int n = mod_openssl_ssl_conf_proto_val(srv, maxb, 1);
3572 switch (n) {
3573 case WOLFSSL_SSLV3:
3574 wolfSSL_CTX_set_options(s->ssl_ctx, WOLFSSL_OP_NO_TLSv1);
3575 __attribute_fallthrough__
3576 case WOLFSSL_TLSV1:
3577 wolfSSL_CTX_set_options(s->ssl_ctx, WOLFSSL_OP_NO_TLSv1_1);
3578 __attribute_fallthrough__
3579 case WOLFSSL_TLSV1_1:
3580 wolfSSL_CTX_set_options(s->ssl_ctx, WOLFSSL_OP_NO_TLSv1_2);
3581 __attribute_fallthrough__
3582 case WOLFSSL_TLSV1_2:
3583 wolfSSL_CTX_set_options(s->ssl_ctx, WOLFSSL_OP_NO_TLSv1_3);
3584 __attribute_fallthrough__
3585 case WOLFSSL_TLSV1_3:
3586 default:
3587 break;
3588 }
3589 #endif
3590 }
3591
3592 if (cipherstring && !buffer_is_blank(cipherstring)) {
3593 /* Disable support for low encryption ciphers */
3594 buffer_append_string_len(cipherstring,
3595 CONST_STR_LEN(":!aNULL:!eNULL:!EXP"));
3596 if (SSL_CTX_set_cipher_list(s->ssl_ctx, cipherstring->ptr) != 1) {
3597 log_error(srv->errh, __FILE__, __LINE__,
3598 "SSL: %s", ERR_error_string(ERR_get_error(), NULL));
3599 rc = -1;
3600 }
3601
3602 if (s->ssl_honor_cipher_order)
3603 SSL_CTX_set_options(s->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
3604 }
3605
3606 if (curves && !buffer_is_blank(curves)) {
3607 if (!mod_openssl_ssl_conf_curves(srv, s, curves))
3608 rc = -1;
3609 }
3610
3611 return rc;
3612 }
3613