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