xref: /lighttpd1.4/src/mod_wolfssl.c (revision 54c07b54)
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 *
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
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
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
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 *
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 *
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
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
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
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
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
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 
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 
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 
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
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
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 *
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 *
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
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 
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 *
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
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
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
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 
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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
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
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
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 *
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
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
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
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 #ifndef DH_set0_pqg /*(added in wolfssl v5.0.0)*/
1850 #define DH_set0_pqg(dh, dh_p, NULL, dh_g) \
1851         ((dh)->p = (dh_p), (dh)->g = (dh_g), (dh_p) != NULL && (dh_g) != NULL)
1852 #endif
1853 /* https://tools.ietf.org/html/rfc7919#appendix-A.1
1854  * A.1.  ffdhe2048
1855  *
1856  * https://ssl-config.mozilla.org/ffdhe2048.txt
1857  * C code generated with: openssl dhparam -C -in ffdhe2048.txt
1858  */
1859 static DH *get_dh2048(void)
1860 {
1861     static unsigned char dhp_2048[] = {
1862         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAD, 0xF8,
1863         0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, 0xAF, 0xDC, 0x56, 0x20,
1864         0x27, 0x3D, 0x3C, 0xF1, 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D,
1865         0x36, 0x95, 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB,
1866         0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, 0x7D, 0x2F,
1867         0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, 0xF6, 0x81, 0xB2, 0x02,
1868         0xAE, 0xC4, 0x61, 0x7A, 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD,
1869         0x65, 0x61, 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0,
1870         0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, 0xB5, 0x57,
1871         0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, 0x98, 0x4F, 0x0C, 0x70,
1872         0xE0, 0xE6, 0x8B, 0x77, 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF,
1873         0xE8, 0x72, 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
1874         0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, 0xBC, 0x0A,
1875         0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, 0xD1, 0x08, 0xA9, 0x4B,
1876         0xB2, 0xC8, 0xE3, 0xFB, 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7,
1877         0xF4, 0x68, 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4,
1878         0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, 0x0B, 0x07,
1879         0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, 0x9E, 0x02, 0xFC, 0xE1,
1880         0xCD, 0xF7, 0xE2, 0xEC, 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34,
1881         0x2F, 0x61, 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF,
1882         0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, 0xC3, 0xFE,
1883         0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, 0x3B, 0xB5, 0xFC, 0xBC,
1884         0x2E, 0xC2, 0x20, 0x05, 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16,
1885         0x83, 0xB2, 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
1886         0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, 0xFF, 0xFF,
1887         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
1888     };
1889     static unsigned char dhg_2048[] = {
1890         0x02
1891     };
1892     DH *dh = DH_new();
1893     BIGNUM *p, *g;
1894 
1895     if (dh == NULL)
1896         return NULL;
1897     p = BN_bin2bn(dhp_2048, sizeof(dhp_2048), NULL);
1898     g = BN_bin2bn(dhg_2048, sizeof(dhg_2048), NULL);
1899     if (p == NULL || g == NULL || !DH_set0_pqg(dh, p, NULL, g)) {
1900         DH_free(dh);
1901         BN_free(p);
1902         BN_free(g);
1903         return NULL;
1904     }
1905     return dh;
1906 }
1907 #endif
1908 
1909 
1910 static int
1911 mod_openssl_ssl_conf_curves(server *srv, plugin_config_socket *s, const buffer *ssl_ec_curve)
1912 {
1913     /* Support for Elliptic-Curve Diffie-Hellman key exchange */
1914     /* OpenSSL only supports the "named curves" from RFC 4492, section 5.1.1. */
1915     const char *curve = ssl_ec_curve ? ssl_ec_curve->ptr : "prime256v1";
1916     int nid = wolfSSL_OBJ_sn2nid(curve);
1917     if (nid) {
1918         EC_KEY * const ecdh = EC_KEY_new_by_curve_name(nid);
1919         if (ecdh == NULL) {
1920             log_error(srv->errh, __FILE__, __LINE__,
1921               "SSL: Unable to create curve %s", curve);
1922             return 0;
1923         }
1924         wolfSSL_SSL_CTX_set_tmp_ecdh(s->ssl_ctx, ecdh);
1925         SSL_CTX_set_options(s->ssl_ctx, SSL_OP_SINGLE_ECDH_USE);
1926         EC_KEY_free(ecdh);
1927         return 1;
1928     }
1929     else {
1930         log_error(srv->errh, __FILE__, __LINE__,
1931           "SSL: Unknown curve name %s", curve);
1932         return 0;
1933     }
1934 }
1935 
1936 
1937 static int
1938 network_init_ssl (server *srv, plugin_config_socket *s, plugin_data *p)
1939 {
1940     /* load SSL certificates */
1941 
1942       #ifndef SSL_OP_NO_COMPRESSION
1943       #define SSL_OP_NO_COMPRESSION 0
1944       #endif
1945         long ssloptions = SSL_OP_ALL
1946                         | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
1947                         | SSL_OP_NO_COMPRESSION;
1948 
1949       #if LIBWOLFSSL_VERSION_HEX >= 0x04002000
1950         s->ssl_ctx = (!s->ssl_use_sslv2 && !s->ssl_use_sslv3)
1951           ? SSL_CTX_new(TLS_server_method())
1952           : SSL_CTX_new(SSLv23_server_method());
1953       #else
1954         s->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
1955       #endif
1956         if (NULL == s->ssl_ctx) {
1957             log_error(srv->errh, __FILE__, __LINE__,
1958               "SSL: %s", ERR_error_string(ERR_get_error(), NULL));
1959             return -1;
1960         }
1961 
1962       #ifdef SSL_OP_NO_RENEGOTIATION /* openssl 1.1.0 */
1963         if (s->ssl_disable_client_renegotiation)
1964             ssloptions |= SSL_OP_NO_RENEGOTIATION;
1965       #endif
1966 
1967         /* completely useless identifier;
1968          * required for client cert verification to work with sessions */
1969         if (0 == SSL_CTX_set_session_id_context(
1970                    s->ssl_ctx,(const unsigned char*)CONST_STR_LEN("lighttpd"))){
1971             log_error(srv->errh, __FILE__, __LINE__,
1972               "SSL: failed to set session context: %s",
1973               ERR_error_string(ERR_get_error(), NULL));
1974             return -1;
1975         }
1976 
1977       #if !defined(NO_SESSION_CACHE)
1978         const int disable_sess_cache =
1979           !config_feature_bool(srv, "ssl.session-cache", 0);
1980         if (disable_sess_cache)
1981             /* disable session cache; session tickets are preferred */
1982             SSL_CTX_set_session_cache_mode(s->ssl_ctx,
1983                                              SSL_SESS_CACHE_OFF
1984                                            | SSL_SESS_CACHE_NO_AUTO_CLEAR
1985                                            | SSL_SESS_CACHE_NO_INTERNAL);
1986       #endif
1987 
1988         if (s->ssl_empty_fragments) {
1989           #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
1990             ssloptions &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
1991           #else
1992             ssloptions &= ~0x00000800L; /* hardcode constant */
1993             log_error(srv->errh, __FILE__, __LINE__,
1994               "WARNING: SSL: 'insert empty fragments' not supported by the "
1995               "openssl version used to compile lighttpd with");
1996           #endif
1997         }
1998 
1999         SSL_CTX_set_options(s->ssl_ctx, ssloptions);
2000         SSL_CTX_set_info_callback(s->ssl_ctx, ssl_info_callback);
2001 
2002         /*(wolfSSL does not support SSLv2)*/
2003 
2004         if (!s->ssl_use_sslv3 && 0 != SSL_OP_NO_SSLv3) {
2005             /* disable SSLv3 */
2006             if ((SSL_OP_NO_SSLv3
2007                  & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv3))
2008                 != SSL_OP_NO_SSLv3) {
2009                 log_error(srv->errh, __FILE__, __LINE__,
2010                   "SSL: %s", ERR_error_string(ERR_get_error(), NULL));
2011                 return -1;
2012             }
2013         }
2014 
2015         if (s->ssl_cipher_list) {
2016             /* Disable support for low encryption ciphers */
2017             if (SSL_CTX_set_cipher_list(s->ssl_ctx,s->ssl_cipher_list->ptr)!=1){
2018                 log_error(srv->errh, __FILE__, __LINE__,
2019                   "SSL: %s", ERR_error_string(ERR_get_error(), NULL));
2020                 return -1;
2021             }
2022 
2023             if (s->ssl_honor_cipher_order) {
2024                 SSL_CTX_set_options(s->ssl_ctx,SSL_OP_CIPHER_SERVER_PREFERENCE);
2025             }
2026         }
2027 
2028       #ifdef SSL_OP_PRIORITIZE_CHACHA /*(openssl 1.1.1)*/
2029         if (s->ssl_honor_cipher_order)
2030             SSL_CTX_set_options(s->ssl_ctx, SSL_OP_PRIORITIZE_CHACHA);
2031       #endif
2032 
2033       #ifndef NO_DH
2034       {
2035         DH *dh;
2036         /* Support for Diffie-Hellman key exchange */
2037         if (s->ssl_dh_file) {
2038             const char *fn = s->ssl_dh_file->ptr;
2039             off_t dlen = 1*1024*1024;/*(arbitrary limit: 1 MB; expect < 1 KB)*/
2040             char *data = fdevent_load_file(fn, &dlen, srv->errh, malloc, free);
2041             int rc = (NULL != data) ? 0 : -1;
2042             if (0 == rc)
2043                   wolfSSL_CTX_SetTmpDH_buffer(s->ssl_ctx, (unsigned char *)data,
2044                                               (long)dlen, WOLFSSL_FILETYPE_PEM);
2045             if (dlen) ck_memzero(data, dlen);
2046             free(data);
2047             if (rc < 0) {
2048                 log_error(srv->errh, __FILE__, __LINE__,
2049                   "SSL: Unable to read DH params from file %s",
2050                   s->ssl_dh_file->ptr);
2051                 return -1;
2052             }
2053         }
2054         else {
2055             dh = get_dh2048();
2056             if (dh == NULL) {
2057                 log_error(srv->errh, __FILE__, __LINE__,
2058                   "SSL: get_dh2048() failed");
2059                 return -1;
2060             }
2061             SSL_CTX_set_tmp_dh(s->ssl_ctx,dh);
2062             DH_free(dh);
2063         }
2064         SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_DH_USE);
2065       }
2066       #else
2067         if (s->ssl_dh_file) {
2068             log_error(srv->errh, __FILE__, __LINE__,
2069               "SSL: openssl compiled without DH support, "
2070               "can't load parameters from %s", s->ssl_dh_file->ptr);
2071         }
2072       #endif
2073 
2074         if (!mod_openssl_ssl_conf_curves(srv, s, s->ssl_ec_curve))
2075             return -1;
2076 
2077       #ifdef HAVE_SESSION_TICKET
2078         wolfSSL_CTX_set_tlsext_ticket_key_cb(s->ssl_ctx, ssl_tlsext_ticket_key_cb);
2079       #endif
2080 
2081       #ifdef HAVE_OCSP
2082         wolfSSL_CTX_set_tlsext_status_cb(s->ssl_ctx, ssl_tlsext_status_cb);
2083       #endif
2084 
2085         /* load all ssl.ca-files specified in the config into each SSL_CTX
2086          * XXX: This might be a bit excessive, but are all trusted CAs
2087          *      TODO: prefer to load on-demand in mod_openssl_cert_cb()
2088          *            for openssl >= 1.0.2 */
2089         if (!mod_wolfssl_load_ca_files(s->ssl_ctx, p, srv))
2090             return -1;
2091 
2092         if (s->ssl_verifyclient) {
2093             if (NULL == s->ssl_ca_file) {
2094                 log_error(srv->errh, __FILE__, __LINE__,
2095                   "SSL: You specified ssl.verifyclient.activate "
2096                   "but no ssl.verifyclient.ca-file");
2097                 return -1;
2098             }
2099           #ifndef OPENSSL_ALL
2100                 log_error(srv->errh, __FILE__, __LINE__,
2101                   "SSL: You specified ssl.verifyclient.activate "
2102                   "but wolfssl library built without necessary support");
2103                 return -1;
2104           #else
2105             /* Before wolfssl 4.6.0, wolfSSL_dup_CA_list() is a stub function
2106              * which returns NULL, so DN names in cert request are not set here.
2107              * (A patch has been submitted to WolfSSL add is part of 4.6.0)
2108              * https://github.com/wolfSSL/wolfssl/pull/3098 */
2109             STACK_OF(X509_NAME) * const cert_names = s->ssl_ca_dn_file
2110               ? s->ssl_ca_dn_file
2111               : s->ssl_ca_file->names;
2112             wolfSSL_CTX_set_client_CA_list(s->ssl_ctx,
2113                                            wolfSSL_dup_CA_list(cert_names));
2114             int mode = SSL_VERIFY_PEER;
2115             if (s->ssl_verifyclient_enforce) {
2116                 mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2117             }
2118             wolfSSL_CTX_set_verify(s->ssl_ctx, mode, verify_callback);
2119             wolfSSL_CTX_set_verify_depth(s->ssl_ctx,
2120                                          s->ssl_verifyclient_depth + 1);
2121           #endif
2122             if (s->ssl_ca_crl_file) {
2123                 if (!mod_wolfssl_load_cacrls(s->ssl_ctx,s->ssl_ca_crl_file,srv))
2124                     return -1;
2125             }
2126         }
2127 
2128         if (1 != mod_wolfssl_CTX_use_certificate_chain_file(
2129                    s->ssl_ctx, s->pc->ssl_pemfile->ptr, srv->errh))
2130             return -1;
2131 
2132         buffer *k = s->pc->ssl_pemfile_pkey;
2133         if (1 != wolfSSL_CTX_use_PrivateKey_buffer(s->ssl_ctx,
2134                                                    (unsigned char *)k->ptr,
2135                                                    (int)buffer_clen(k),
2136                                                    WOLFSSL_FILETYPE_ASN1)) {
2137             log_error(srv->errh, __FILE__, __LINE__,
2138               "SSL: %s %s %s", ERR_error_string(ERR_get_error(), NULL),
2139               s->pc->ssl_pemfile->ptr, s->pc->ssl_privkey->ptr);
2140             return -1;
2141         }
2142 
2143         if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
2144             log_error(srv->errh, __FILE__, __LINE__,
2145               "SSL: Private key does not match the certificate public key, "
2146               "reason: %s %s %s", ERR_error_string(ERR_get_error(), NULL),
2147               s->pc->ssl_pemfile->ptr, s->pc->ssl_privkey->ptr);
2148             return -1;
2149         }
2150 
2151         SSL_CTX_set_default_read_ahead(s->ssl_ctx, s->ssl_read_ahead);
2152         wolfSSL_CTX_set_mode(s->ssl_ctx,
2153                              SSL_MODE_ENABLE_PARTIAL_WRITE);
2154         wolfSSL_CTX_set_mode(s->ssl_ctx, /*(wolfSSL default mode)*/
2155                              WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
2156       #ifdef wolfSSL_SSL_MODE_RELEASE_BUFFERS
2157         wolfSSL_CTX_set_mode(s->ssl_ctx, /*(not currently implemented)*/
2158                              wolfSSL_SSL_MODE_RELEASE_BUFFERS);
2159       #endif
2160 
2161       #ifdef HAVE_TLS_EXTENSIONS
2162         /*(wolfSSL preprocessor defines are obnoxious)*/
2163         /*(code should be HAVE_SNI, but is hidden by OPENSSL_ALL
2164          * even though the comment in wolfssl code on the #endif
2165          * says (OPENSSL_ALL
2166          *       || (OPENSSL_EXTRA
2167          *           && (HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_LIGHTY)))
2168          * and sniRecvCb sniRecvCbArg are hidden by *different* set of defines
2169          * in wolfssl/internal.h)
2170          * Note: wolfSSL SNI callbacks members not present unless wolfSSL is
2171          * built OPENSSL_ALL or some additional combination of preprocessor
2172          * defines.  The following should work with more recent wolfSSL versions
2173          * (and HAVE_LIGHTY is not sufficient in wolfssl <= 4.5.0) */
2174        #if defined(OPENSSL_ALL) \
2175         || (defined(OPENSSL_EXTRA) \
2176             && (defined(HAVE_STUNNEL) \
2177                 || defined(WOLFSSL_NGINX) \
2178                 || defined(WOLFSSL_HAPROXY)))
2179        #else
2180        #undef HAVE_SNI
2181        #endif
2182        #ifdef HAVE_SNI
2183         wolfSSL_CTX_set_servername_callback(
2184             s->ssl_ctx, network_ssl_servername_callback);
2185         wolfSSL_CTX_set_servername_arg(s->ssl_ctx, srv);
2186        #else
2187         log_error(srv->errh, __FILE__, __LINE__,
2188           "SSL: WARNING: SNI callbacks *crippled* in wolfSSL library build");
2189         UNUSED(network_ssl_servername_callback);
2190        #endif
2191 
2192        #ifdef HAVE_ALPN
2193        #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
2194         SSL_CTX_set_alpn_select_cb(s->ssl_ctx,mod_openssl_alpn_select_cb,NULL);
2195        #endif
2196        #endif
2197       #endif
2198 
2199         if (!s->ssl_use_sslv3 && !s->ssl_use_sslv2
2200             && wolfSSL_CTX_SetMinVersion(s->ssl_ctx, WOLFSSL_TLSV1_2)
2201                != WOLFSSL_SUCCESS)
2202             return -1;
2203 
2204         if (s->ssl_conf_cmd && s->ssl_conf_cmd->used) {
2205             if (0 != mod_openssl_ssl_conf_cmd(srv, s)) return -1;
2206         }
2207 
2208         return 0;
2209 }
2210 
2211 
2212 static int
2213 mod_openssl_set_defaults_sockets(server *srv, plugin_data *p)
2214 {
2215     static const config_plugin_keys_t cpk[] = {
2216       { CONST_STR_LEN("ssl.engine"),
2217         T_CONFIG_BOOL,
2218         T_CONFIG_SCOPE_CONNECTION }
2219      ,{ CONST_STR_LEN("ssl.cipher-list"),
2220         T_CONFIG_STRING,
2221         T_CONFIG_SCOPE_CONNECTION }
2222      ,{ CONST_STR_LEN("ssl.honor-cipher-order"),
2223         T_CONFIG_BOOL,
2224         T_CONFIG_SCOPE_CONNECTION }
2225      ,{ CONST_STR_LEN("ssl.dh-file"),
2226         T_CONFIG_STRING,
2227         T_CONFIG_SCOPE_CONNECTION }
2228      ,{ CONST_STR_LEN("ssl.ec-curve"),
2229         T_CONFIG_STRING,
2230         T_CONFIG_SCOPE_CONNECTION }
2231      ,{ CONST_STR_LEN("ssl.openssl.ssl-conf-cmd"),
2232         T_CONFIG_ARRAY_KVSTRING,
2233         T_CONFIG_SCOPE_CONNECTION }
2234      ,{ CONST_STR_LEN("ssl.pemfile"), /* included to process global scope */
2235         T_CONFIG_STRING,
2236         T_CONFIG_SCOPE_CONNECTION }
2237      ,{ CONST_STR_LEN("ssl.empty-fragments"),
2238         T_CONFIG_BOOL,
2239         T_CONFIG_SCOPE_CONNECTION }
2240      ,{ CONST_STR_LEN("ssl.use-sslv2"),
2241         T_CONFIG_BOOL,
2242         T_CONFIG_SCOPE_CONNECTION }
2243      ,{ CONST_STR_LEN("ssl.use-sslv3"),
2244         T_CONFIG_BOOL,
2245         T_CONFIG_SCOPE_CONNECTION }
2246      ,{ CONST_STR_LEN("ssl.stek-file"),
2247         T_CONFIG_STRING,
2248         T_CONFIG_SCOPE_SERVER }
2249      ,{ NULL, 0,
2250         T_CONFIG_UNSET,
2251         T_CONFIG_SCOPE_UNSET }
2252     };
2253     /* WolfSSL does not have mapping for "HIGH" */
2254     /* cipher list is (current) output of "openssl ciphers HIGH" */
2255     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 };
2256 
2257     p->ssl_ctxs = calloc(srv->config_context->used, sizeof(plugin_ssl_ctx));
2258     force_assert(p->ssl_ctxs);
2259 
2260     int rc = HANDLER_GO_ON;
2261     plugin_data_base srvplug;
2262     memset(&srvplug, 0, sizeof(srvplug));
2263     plugin_data_base * const ps = &srvplug;
2264     if (!config_plugin_values_init(srv, ps, cpk, "mod_openssl"))
2265         return HANDLER_ERROR;
2266 
2267     plugin_config_socket defaults;
2268     memset(&defaults, 0, sizeof(defaults));
2269     defaults.ssl_honor_cipher_order = 1;
2270     defaults.ssl_cipher_list = &default_ssl_cipher_list;
2271 
2272     /* process and validate config directives for global and $SERVER["socket"]
2273      * (init i to 0 if global context; to 1 to skip empty global context) */
2274     for (int i = !ps->cvlist[0].v.u2[1]; i < ps->nconfig; ++i) {
2275         config_cond_info cfginfo;
2276         config_get_config_cond_info(&cfginfo, (uint32_t)ps->cvlist[i].k_id);
2277         int is_socket_scope = (0 == i || cfginfo.comp == COMP_SERVER_SOCKET);
2278         int count_not_engine = 0;
2279 
2280         plugin_config_socket conf;
2281         memcpy(&conf, &defaults, sizeof(conf));
2282 
2283         /*(preserve prior behavior; not inherited)*/
2284         /*(forcing inheritance might break existing configs where SSL is enabled
2285          * by default in the global scope, but not $SERVER["socket"]=="*:80") */
2286         conf.ssl_enabled = 0;
2287 
2288         config_plugin_value_t *cpv = ps->cvlist + ps->cvlist[i].v.u2[0];
2289         for (; -1 != cpv->k_id; ++cpv) {
2290             /* ignore ssl.pemfile (k_id=6); included to process global scope */
2291             if (!is_socket_scope && cpv->k_id != 6) {
2292                 log_error(srv->errh, __FILE__, __LINE__,
2293                   "%s is valid only in global scope or "
2294                   "$SERVER[\"socket\"] condition", cpk[cpv->k_id].k);
2295                 continue;
2296             }
2297             ++count_not_engine;
2298             switch (cpv->k_id) {
2299               case 0: /* ssl.engine */
2300                 conf.ssl_enabled = (0 != cpv->v.u);
2301                 --count_not_engine;
2302                 break;
2303               case 1: /* ssl.cipher-list */
2304                 if (!buffer_is_blank(cpv->v.b))
2305                     conf.ssl_cipher_list = cpv->v.b;
2306                 break;
2307               case 2: /* ssl.honor-cipher-order */
2308                 conf.ssl_honor_cipher_order = (0 != cpv->v.u);
2309                 break;
2310               case 3: /* ssl.dh-file */
2311                 if (!buffer_is_blank(cpv->v.b))
2312                     conf.ssl_dh_file = cpv->v.b;
2313                 break;
2314               case 4: /* ssl.ec-curve */
2315                 if (!buffer_is_blank(cpv->v.b))
2316                     conf.ssl_ec_curve = cpv->v.b;
2317                 break;
2318               case 5: /* ssl.openssl.ssl-conf-cmd */
2319                 *(const array **)&conf.ssl_conf_cmd = cpv->v.a;
2320                 break;
2321               case 6: /* ssl.pemfile */
2322                 /* ignore here; included to process global scope when
2323                  * ssl.pemfile is set, but ssl.engine is not "enable" */
2324                 break;
2325               case 7: /* ssl.empty-fragments */
2326                 conf.ssl_empty_fragments = (0 != cpv->v.u);
2327                 log_error(srv->errh, __FILE__, __LINE__, "SSL: "
2328                   "ssl.empty-fragments is deprecated and will soon be "
2329                   "removed.  It is disabled by default.");
2330                 if (conf.ssl_empty_fragments)
2331                     log_error(srv->errh, __FILE__, __LINE__, "SSL: "
2332                       "If needed, use: ssl.openssl.ssl-conf-cmd = "
2333                       "(\"Options\" => \"EmptyFragments\")");
2334                 log_error(srv->errh, __FILE__, __LINE__, "SSL: "
2335                   "ssl.empty-fragments is a "
2336                   "counter-measure against a SSL 3.0/TLS 1.0 protocol "
2337                   "vulnerability affecting CBC ciphers, which cannot be handled"
2338                   " by some broken (Microsoft) SSL implementations.");
2339                 break;
2340               case 8: /* ssl.use-sslv2 */
2341                 conf.ssl_use_sslv2 = (0 != cpv->v.u);
2342                 log_error(srv->errh, __FILE__, __LINE__, "SSL: "
2343                   "ssl.use-sslv2 is deprecated and will soon be removed.  "
2344                   "It is disabled by default.  "
2345                   "Many modern TLS libraries no longer support SSLv2.");
2346                 break;
2347               case 9: /* ssl.use-sslv3 */
2348                 conf.ssl_use_sslv3 = (0 != cpv->v.u);
2349                 log_error(srv->errh, __FILE__, __LINE__, "SSL: "
2350                   "ssl.use-sslv3 is deprecated and will soon be removed.  "
2351                   "It is disabled by default.  "
2352                   "Many modern TLS libraries no longer support SSLv3.");
2353                 if (conf.ssl_use_sslv3)
2354                     log_error(srv->errh, __FILE__, __LINE__, "SSL: "
2355                       "If needed, use: ssl.openssl.ssl-conf-cmd = "
2356                       "(\"MinProtocol\" => \"SSLv3\")");
2357                 break;
2358               case 10:/* ssl.stek-file */
2359                 if (!buffer_is_blank(cpv->v.b))
2360                     p->ssl_stek_file = cpv->v.b->ptr;
2361                 break;
2362               default:/* should not happen */
2363                 break;
2364             }
2365         }
2366         if (HANDLER_GO_ON != rc) break;
2367         if (0 == i) memcpy(&defaults, &conf, sizeof(conf));
2368 
2369         if (0 != i && !conf.ssl_enabled) continue;
2370 
2371         /* fill plugin_config_socket with global context then $SERVER["socket"]
2372          * only for directives directly in current $SERVER["socket"] condition*/
2373 
2374         /*conf.pc                     = p->defaults.pc;*/
2375         conf.ssl_ca_file              = p->defaults.ssl_ca_file;
2376         conf.ssl_ca_dn_file           = p->defaults.ssl_ca_dn_file;
2377         conf.ssl_ca_crl_file          = p->defaults.ssl_ca_crl_file;
2378         conf.ssl_verifyclient         = p->defaults.ssl_verifyclient;
2379         conf.ssl_verifyclient_enforce = p->defaults.ssl_verifyclient_enforce;
2380         conf.ssl_verifyclient_depth   = p->defaults.ssl_verifyclient_depth;
2381         conf.ssl_read_ahead           = p->defaults.ssl_read_ahead;
2382 
2383         int sidx = ps->cvlist[i].k_id;
2384         for (int j = !p->cvlist[0].v.u2[1]; j < p->nconfig; ++j) {
2385             if (p->cvlist[j].k_id != sidx) continue;
2386             /*if (0 == sidx) break;*//*(repeat to get ssl_pemfile,ssl_privkey)*/
2387             cpv = p->cvlist + p->cvlist[j].v.u2[0];
2388             for (; -1 != cpv->k_id; ++cpv) {
2389                 ++count_not_engine;
2390                 switch (cpv->k_id) {
2391                   case 0: /* ssl.pemfile */
2392                     if (cpv->vtype == T_CONFIG_LOCAL)
2393                         conf.pc = cpv->v.v;
2394                     break;
2395                   case 2: /* ssl.ca-file */
2396                     if (cpv->vtype == T_CONFIG_LOCAL)
2397                         conf.ssl_ca_file = cpv->v.v;
2398                     break;
2399                   case 3: /* ssl.ca-dn-file */
2400                     if (cpv->vtype == T_CONFIG_LOCAL)
2401                         conf.ssl_ca_dn_file = cpv->v.v;
2402                     break;
2403                   case 4: /* ssl.ca-crl-file */
2404                     if (!buffer_is_blank(cpv->v.b))
2405                         conf.ssl_ca_crl_file = cpv->v.b;
2406                     break;
2407                   case 5: /* ssl.read-ahead */
2408                     conf.ssl_read_ahead = (0 != cpv->v.u);
2409                     break;
2410                   case 6: /* ssl.disable-client-renegotiation */
2411                     conf.ssl_disable_client_renegotiation = (0 != cpv->v.u);
2412                     break;
2413                   case 7: /* ssl.verifyclient.activate */
2414                     conf.ssl_verifyclient = (0 != cpv->v.u);
2415                     break;
2416                   case 8: /* ssl.verifyclient.enforce */
2417                     conf.ssl_verifyclient_enforce = (0 != cpv->v.u);
2418                     break;
2419                   case 9: /* ssl.verifyclient.depth */
2420                     conf.ssl_verifyclient_depth = (unsigned char)cpv->v.shrt;
2421                     break;
2422                  #if 0    /*(cpk->k_id remapped in mod_openssl_set_defaults())*/
2423                   case 15:/* ssl.verifyclient.ca-file */
2424                   case 16:/* ssl.verifyclient.ca-dn-file */
2425                   case 17:/* ssl.verifyclient.ca-crl-file */
2426                  #endif
2427                   default:
2428                     break;
2429                 }
2430             }
2431             break;
2432         }
2433 
2434         if (NULL == conf.pc) {
2435             if (0 == i && !conf.ssl_enabled) continue;
2436             if (0 != i) {
2437                 /* inherit ssl settings from global scope
2438                  * (if only ssl.engine = "enable" and no other ssl.* settings)
2439                  * (This is for convenience when defining both IPv4 and IPv6
2440                  *  and desiring to inherit the ssl config from global context
2441                  *  without having to duplicate the directives)*/
2442                 if (count_not_engine
2443                     || (conf.ssl_enabled && NULL == p->ssl_ctxs[0].ssl_ctx)) {
2444                     log_error(srv->errh, __FILE__, __LINE__,
2445                       "ssl.pemfile has to be set in same $SERVER[\"socket\"] scope "
2446                       "as other ssl.* directives, unless only ssl.engine is set, "
2447                       "inheriting ssl.* from global scope");
2448                     rc = HANDLER_ERROR;
2449                     continue;
2450                 }
2451                 plugin_ssl_ctx * const s = p->ssl_ctxs + sidx;
2452                 *s = *p->ssl_ctxs;/*(copy struct of ssl_ctx from global scope)*/
2453                 continue;
2454             }
2455             /* PEM file is required */
2456             log_error(srv->errh, __FILE__, __LINE__,
2457               "ssl.pemfile has to be set when ssl.engine = \"enable\"");
2458             rc = HANDLER_ERROR;
2459             continue;
2460         }
2461 
2462         /* configure ssl_ctx for socket */
2463 
2464         /*conf.ssl_ctx = NULL;*//*(filled by network_init_ssl() even on error)*/
2465         if (0 == network_init_ssl(srv, &conf, p)) {
2466             plugin_ssl_ctx * const s = p->ssl_ctxs + sidx;
2467             s->ssl_ctx = conf.ssl_ctx;
2468         }
2469         else {
2470             SSL_CTX_free(conf.ssl_ctx);
2471             rc = HANDLER_ERROR;
2472         }
2473     }
2474 
2475   #ifdef HAVE_SESSION_TICKET
2476     if (rc == HANDLER_GO_ON && ssl_is_init)
2477         mod_openssl_session_ticket_key_check(p, log_epoch_secs);
2478   #endif
2479 
2480     free(srvplug.cvlist);
2481     return rc;
2482 }
2483 
2484 
2485 SETDEFAULTS_FUNC(mod_openssl_set_defaults)
2486 {
2487     static const config_plugin_keys_t cpk[] = {
2488       { CONST_STR_LEN("ssl.pemfile"),
2489         T_CONFIG_STRING,
2490         T_CONFIG_SCOPE_CONNECTION }
2491      ,{ CONST_STR_LEN("ssl.privkey"),
2492         T_CONFIG_STRING,
2493         T_CONFIG_SCOPE_CONNECTION }
2494      ,{ CONST_STR_LEN("ssl.ca-file"),
2495         T_CONFIG_STRING,
2496         T_CONFIG_SCOPE_CONNECTION }
2497      ,{ CONST_STR_LEN("ssl.ca-dn-file"),
2498         T_CONFIG_STRING,
2499         T_CONFIG_SCOPE_CONNECTION }
2500      ,{ CONST_STR_LEN("ssl.ca-crl-file"),
2501         T_CONFIG_STRING,
2502         T_CONFIG_SCOPE_CONNECTION }
2503      ,{ CONST_STR_LEN("ssl.read-ahead"),
2504         T_CONFIG_BOOL,
2505         T_CONFIG_SCOPE_CONNECTION }
2506      ,{ CONST_STR_LEN("ssl.disable-client-renegotiation"),
2507         T_CONFIG_BOOL,
2508         T_CONFIG_SCOPE_CONNECTION }
2509      ,{ CONST_STR_LEN("ssl.verifyclient.activate"),
2510         T_CONFIG_BOOL,
2511         T_CONFIG_SCOPE_CONNECTION }
2512      ,{ CONST_STR_LEN("ssl.verifyclient.enforce"),
2513         T_CONFIG_BOOL,
2514         T_CONFIG_SCOPE_CONNECTION }
2515      ,{ CONST_STR_LEN("ssl.verifyclient.depth"),
2516         T_CONFIG_SHORT,
2517         T_CONFIG_SCOPE_CONNECTION }
2518      ,{ CONST_STR_LEN("ssl.verifyclient.username"),
2519         T_CONFIG_STRING,
2520         T_CONFIG_SCOPE_CONNECTION }
2521      ,{ CONST_STR_LEN("ssl.verifyclient.exportcert"),
2522         T_CONFIG_BOOL,
2523         T_CONFIG_SCOPE_CONNECTION }
2524      ,{ CONST_STR_LEN("ssl.acme-tls-1"),
2525         T_CONFIG_STRING,
2526         T_CONFIG_SCOPE_CONNECTION }
2527      ,{ CONST_STR_LEN("ssl.stapling-file"),
2528         T_CONFIG_STRING,
2529         T_CONFIG_SCOPE_CONNECTION }
2530      ,{ CONST_STR_LEN("debug.log-ssl-noise"),
2531         T_CONFIG_BOOL,
2532         T_CONFIG_SCOPE_CONNECTION }
2533      ,{ CONST_STR_LEN("ssl.verifyclient.ca-file"),
2534         T_CONFIG_STRING,
2535         T_CONFIG_SCOPE_CONNECTION }
2536      ,{ CONST_STR_LEN("ssl.verifyclient.ca-dn-file"),
2537         T_CONFIG_STRING,
2538         T_CONFIG_SCOPE_CONNECTION }
2539      ,{ CONST_STR_LEN("ssl.verifyclient.ca-crl-file"),
2540         T_CONFIG_STRING,
2541         T_CONFIG_SCOPE_CONNECTION }
2542      ,{ NULL, 0,
2543         T_CONFIG_UNSET,
2544         T_CONFIG_SCOPE_UNSET }
2545     };
2546 
2547     plugin_data * const p = p_d;
2548     p->srv = srv;
2549     p->cafiles = array_init(0);
2550     if (!config_plugin_values_init(srv, p, cpk, "mod_openssl"))
2551         return HANDLER_ERROR;
2552 
2553     const buffer *default_ssl_ca_crl_file = NULL;
2554 
2555     /* process and validate config directives
2556      * (init i to 0 if global context; to 1 to skip empty global context) */
2557     for (int i = !p->cvlist[0].v.u2[1]; i < p->nconfig; ++i) {
2558         config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0];
2559         config_plugin_value_t *pemfile = NULL;
2560         config_plugin_value_t *privkey = NULL;
2561         const buffer *ssl_stapling_file = NULL;
2562         const buffer *ssl_ca_file = NULL;
2563         const buffer *ssl_ca_dn_file = NULL;
2564         const buffer *ssl_ca_crl_file = NULL;
2565         X509_STORE *ca_store = NULL;
2566         for (; -1 != cpv->k_id; ++cpv) {
2567             switch (cpv->k_id) {
2568               case 0: /* ssl.pemfile */
2569                 if (!buffer_is_blank(cpv->v.b)) pemfile = cpv;
2570                 break;
2571               case 1: /* ssl.privkey */
2572                 if (!buffer_is_blank(cpv->v.b)) privkey = cpv;
2573                 break;
2574               case 15:/* ssl.verifyclient.ca-file */
2575                 cpv->k_id = 2;
2576                 __attribute_fallthrough__
2577               case 2: /* ssl.ca-file */
2578                 if (buffer_is_blank(cpv->v.b)) break;
2579                 if (!mod_openssl_init_once_openssl(srv)) return HANDLER_ERROR;
2580                 ssl_ca_file = cpv->v.b;
2581                 cpv->v.v = mod_wolfssl_load_cacerts(ssl_ca_file, srv->errh);
2582                 if (NULL != cpv->v.v) {
2583                     cpv->vtype = T_CONFIG_LOCAL;
2584                     ca_store = ((plugin_cacerts *)cpv->v.v)->certs;
2585                 }
2586                 else {
2587                     log_error(srv->errh, __FILE__, __LINE__, "SSL: %s %s",
2588                       ERR_error_string(ERR_get_error(), NULL),
2589                       ssl_ca_file->ptr);
2590                     return HANDLER_ERROR;
2591                 }
2592                 break;
2593               case 16:/* ssl.verifyclient.ca-dn-file */
2594                 cpv->k_id = 3;
2595                 __attribute_fallthrough__
2596               case 3: /* ssl.ca-dn-file */
2597                 if (buffer_is_blank(cpv->v.b)) break;
2598                 if (!mod_openssl_init_once_openssl(srv)) return HANDLER_ERROR;
2599                 ssl_ca_dn_file = cpv->v.b;
2600                #ifndef OPENSSL_ALL
2601                 {
2602                     log_error(srv->errh, __FILE__, __LINE__,
2603                       "SSL: You specified %s but wolfssl library built without "
2604                       "necessary support", cpk[cpv->k_id].k);
2605                     return HANDLER_ERROR;
2606                 }
2607                #endif
2608                 cpv->v.v = mod_wolfssl_load_client_CA_file(ssl_ca_dn_file,
2609                                                            srv->errh);
2610                 if (NULL != cpv->v.v) {
2611                     cpv->vtype = T_CONFIG_LOCAL;
2612                 }
2613                 else {
2614                     log_error(srv->errh, __FILE__, __LINE__, "SSL: %s %s",
2615                       ERR_error_string(ERR_get_error(), NULL),
2616                       ssl_ca_dn_file->ptr);
2617                     return HANDLER_ERROR;
2618                 }
2619                 break;
2620               case 17:/* ssl.verifyclient.ca-crl-file */
2621                 cpv->k_id = 4;
2622                 __attribute_fallthrough__
2623               case 4: /* ssl.ca-crl-file */
2624                 if (buffer_is_blank(cpv->v.b)) break;
2625                 ssl_ca_crl_file = cpv->v.b;
2626                 if (0 == i) default_ssl_ca_crl_file = cpv->v.b;
2627                 break;
2628               case 5: /* ssl.read-ahead */
2629                 break;
2630               case 6: /* ssl.disable-client-renegotiation */
2631                 /* (force disabled, the default, if HTTP/2 enabled in server) */
2632                 if (srv->srvconf.h2proto)
2633                     cpv->v.u = 1; /* disable client renegotiation */
2634                 break;
2635               case 7: /* ssl.verifyclient.activate */
2636               case 8: /* ssl.verifyclient.enforce */
2637                 break;
2638               case 9: /* ssl.verifyclient.depth */
2639                 if (cpv->v.shrt > 255) {
2640                     log_error(srv->errh, __FILE__, __LINE__,
2641                       "%s is absurdly large (%hu); limiting to 255",
2642                       cpk[cpv->k_id].k, cpv->v.shrt);
2643                     cpv->v.shrt = 255;
2644                 }
2645                 break;
2646               case 10:/* ssl.verifyclient.username */
2647                 if (buffer_is_blank(cpv->v.b))
2648                     cpv->v.b = NULL;
2649                 break;
2650               case 11:/* ssl.verifyclient.exportcert */
2651                 break;
2652               case 12:/* ssl.acme-tls-1 */
2653                 if (buffer_is_blank(cpv->v.b))
2654                     cpv->v.b = NULL;
2655                 break;
2656               case 13:/* ssl.stapling-file */
2657                 if (!buffer_is_blank(cpv->v.b))
2658                     ssl_stapling_file = cpv->v.b;
2659                 break;
2660               case 14:/* debug.log-ssl-noise */
2661              #if 0    /*(handled further above)*/
2662               case 15:/* ssl.verifyclient.ca-file */
2663               case 16:/* ssl.verifyclient.ca-dn-file */
2664               case 17:/* ssl.verifyclient.ca-crl-file */
2665              #endif
2666                 break;
2667               default:/* should not happen */
2668                 break;
2669             }
2670         }
2671 
2672         /* p->cafiles for legacy only */
2673         /* load all ssl.ca-files into a single chain */
2674         /*(certificate load order might matter)*/
2675         if (ssl_ca_dn_file)
2676             array_insert_value(p->cafiles, BUF_PTR_LEN(ssl_ca_dn_file));
2677         if (ssl_ca_file)
2678             array_insert_value(p->cafiles, BUF_PTR_LEN(ssl_ca_file));
2679         UNUSED(ca_store);
2680         UNUSED(ssl_ca_crl_file);
2681         UNUSED(default_ssl_ca_crl_file);
2682 
2683         if (pemfile) {
2684           #ifndef HAVE_TLS_EXTENSIONS
2685             config_cond_info cfginfo;
2686             uint32_t j = (uint32_t)p->cvlist[i].k_id;
2687             config_get_config_cond_info(&cfginfo, j);
2688             if (j > 0 && (COMP_SERVER_SOCKET != cfginfo.comp
2689                           || cfginfo.cond != CONFIG_COND_EQ)) {
2690                 if (COMP_HTTP_HOST == cfginfo.comp)
2691                     log_error(srv->errh, __FILE__, __LINE__, "SSL:"
2692                       "can't use ssl.pemfile with $HTTP[\"host\"], "
2693                       "as openssl version does not support TLS extensions");
2694                 else
2695                     log_error(srv->errh, __FILE__, __LINE__, "SSL:"
2696                       "ssl.pemfile only works in SSL socket binding context "
2697                       "as openssl version does not support TLS extensions");
2698                 return HANDLER_ERROR;
2699             }
2700           #endif
2701             if (NULL == privkey) privkey = pemfile;
2702             pemfile->v.v =
2703               network_openssl_load_pemfile(srv, pemfile->v.b, privkey->v.b,
2704                                            ssl_stapling_file);
2705             if (pemfile->v.v)
2706                 pemfile->vtype = T_CONFIG_LOCAL;
2707             else
2708                 return HANDLER_ERROR;
2709         }
2710     }
2711 
2712     p->defaults.ssl_verifyclient = 0;
2713     p->defaults.ssl_verifyclient_enforce = 1;
2714     p->defaults.ssl_verifyclient_depth = 9;
2715     p->defaults.ssl_verifyclient_export_cert = 0;
2716     p->defaults.ssl_disable_client_renegotiation = 1;
2717     p->defaults.ssl_read_ahead = 0;
2718 
2719     /* initialize p->defaults from global config context */
2720     if (p->nconfig > 0 && p->cvlist->v.u2[1]) {
2721         const config_plugin_value_t *cpv = p->cvlist + p->cvlist->v.u2[0];
2722         if (-1 != cpv->k_id)
2723             mod_openssl_merge_config(&p->defaults, cpv);
2724     }
2725 
2726     return mod_openssl_set_defaults_sockets(srv, p);
2727 }
2728 
2729 
2730     /* local_send_buffer is a static buffer of size (LOCAL_SEND_BUFSIZE)
2731      *
2732      * it has to stay at the same location all the time to satisfy the needs
2733      * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE
2734      *
2735      * buffer is allocated once, is NOT realloced (note: not thread-safe)
2736      *
2737      * (Note: above restriction no longer true since SSL_CTX_set_mode() is
2738      *        called with SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)
2739      * */
2740 
2741             /* copy small mem chunks into single large buffer before SSL_write()
2742              * to reduce number times write() called underneath SSL_write() and
2743              * potentially reduce number of packets generated if TCP_NODELAY */
2744 
2745 
2746 static int
2747 mod_openssl_close_notify(handler_ctx *hctx);
2748 
2749 
2750 static int
2751 connection_write_cq_ssl (connection * const con, chunkqueue * const cq, off_t max_bytes)
2752 {
2753     handler_ctx * const hctx = con->plugin_ctx[plugin_data_singleton->id];
2754     SSL * const ssl = hctx->ssl;
2755     log_error_st * const errh = hctx->errh;
2756 
2757     if (__builtin_expect( (0 != hctx->close_notify), 0))
2758         return mod_openssl_close_notify(hctx);
2759 
2760     while (max_bytes > 0 && !chunkqueue_is_empty(cq)) {
2761         char *data = local_send_buffer;
2762         uint32_t data_len = LOCAL_SEND_BUFSIZE < max_bytes
2763           ? LOCAL_SEND_BUFSIZE
2764           : (uint32_t)max_bytes;
2765         int wr;
2766 
2767         if (0 != chunkqueue_peek_data(cq, &data, &data_len, errh)) return -1;
2768         if (__builtin_expect( (0 == data_len), 0)) {
2769             chunkqueue_remove_finished_chunks(cq);
2770             continue;
2771         }
2772 
2773         /**
2774          * SSL_write man-page
2775          *
2776          * WARNING
2777          *        When an SSL_write() operation has to be repeated because of
2778          *        SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be
2779          *        repeated with the same arguments.
2780          */
2781 
2782         ERR_clear_error();
2783         wr = SSL_write(ssl, data, data_len);
2784 
2785         if (__builtin_expect( (hctx->renegotiations > 1), 0)
2786             && hctx->conf.ssl_disable_client_renegotiation) {
2787             log_error(errh, __FILE__, __LINE__,
2788               "SSL: renegotiation initiated by client, killing connection");
2789             return -1;
2790         }
2791 
2792         if (wr <= 0) {
2793             int ssl_r;
2794             unsigned long err;
2795 
2796             switch ((ssl_r = SSL_get_error(ssl, wr))) {
2797             case SSL_ERROR_WANT_READ:
2798                 con->is_readable = -1;
2799                 return 0; /* try again later */
2800             case SSL_ERROR_WANT_WRITE:
2801                 con->is_writable = -1;
2802                 return 0; /* try again later */
2803             case SSL_ERROR_SYSCALL:
2804                 /* perhaps we have error waiting in our error-queue */
2805                 if (0 != (err = ERR_get_error())) {
2806                     do {
2807                         log_error(errh, __FILE__, __LINE__,
2808                           "SSL: %d %d %s",ssl_r,wr,ERR_error_string(err,NULL));
2809                     } while((err = ERR_get_error()));
2810                 } else if (wr == -1) {
2811                     /* no, but we have errno */
2812                     switch(errno) {
2813                     case EPIPE:
2814                     case ECONNRESET:
2815                         return -2;
2816                     default:
2817                         log_perror(errh, __FILE__, __LINE__,
2818                           "SSL: %d %d", ssl_r, wr);
2819                         break;
2820                     }
2821                 } else {
2822                     /* neither error-queue nor errno ? */
2823                     log_perror(errh, __FILE__, __LINE__,
2824                       "SSL (error): %d %d", ssl_r, wr);
2825                 }
2826                 break;
2827 
2828             case SSL_ERROR_ZERO_RETURN:
2829                 /* clean shutdown on the remote side */
2830 
2831                 if (wr == 0) return -2;
2832 
2833                 __attribute_fallthrough__
2834             default:
2835                 while((err = ERR_get_error())) {
2836                     log_error(errh, __FILE__, __LINE__,
2837                       "SSL: %d %d %s", ssl_r, wr, ERR_error_string(err, NULL));
2838                 }
2839                 break;
2840             }
2841             return -1;
2842         }
2843 
2844         chunkqueue_mark_written(cq, wr);
2845         max_bytes -= wr;
2846 
2847         if ((size_t) wr < data_len) break; /* try again later */
2848     }
2849 
2850     return 0;
2851 }
2852 
2853 
2854 static int
2855 connection_read_cq_ssl (connection * const con, chunkqueue * const cq, off_t max_bytes)
2856 {
2857     handler_ctx * const hctx = con->plugin_ctx[plugin_data_singleton->id];
2858     int len;
2859     char *mem = NULL;
2860     size_t mem_len = 0;
2861 
2862     UNUSED(max_bytes);
2863 
2864     if (__builtin_expect( (0 != hctx->close_notify), 0))
2865         return mod_openssl_close_notify(hctx);
2866 
2867     ERR_clear_error();
2868     do {
2869         len = SSL_pending(hctx->ssl);
2870         mem_len = len < 2048 ? 2048 : (size_t)len;
2871         chunk * const ckpt = cq->last;
2872         mem = chunkqueue_get_memory(cq, &mem_len);
2873 
2874         len = SSL_read(hctx->ssl, mem, mem_len);
2875         if (len > 0) {
2876             chunkqueue_use_memory(cq, ckpt, len);
2877             con->bytes_read += len;
2878         } else {
2879             chunkqueue_use_memory(cq, ckpt, 0);
2880         }
2881 
2882         if (hctx->renegotiations > 1
2883             && hctx->conf.ssl_disable_client_renegotiation) {
2884             log_error(hctx->errh, __FILE__, __LINE__,
2885               "SSL: renegotiation initiated by client, killing connection");
2886             return -1;
2887         }
2888 
2889       #ifdef HAVE_ALPN
2890       #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
2891         if (hctx->alpn) {
2892             if (hctx->alpn == MOD_OPENSSL_ALPN_H2) {
2893                 if (0 != mod_openssl_alpn_h2_policy(hctx))
2894                     return -1;
2895             }
2896             else if (hctx->alpn == MOD_OPENSSL_ALPN_ACME_TLS_1) {
2897                 chunkqueue_reset(cq);
2898                 /* initiate handshake in order to send ServerHello.
2899                  * Once TLS handshake is complete, return -1 to result in
2900                  * CON_STATE_ERROR so that socket connection is quickly closed*/
2901                 if (1 == SSL_do_handshake(hctx->ssl)) return -1;
2902                 len = -1;
2903                 break;
2904             }
2905             hctx->alpn = 0;
2906         }
2907       #endif
2908       #endif
2909     } while (len > 0
2910              && (hctx->conf.ssl_read_ahead || SSL_pending(hctx->ssl) > 0));
2911 
2912     if (len < 0) {
2913         int oerrno = errno;
2914         int rc, ssl_err;
2915         switch ((rc = SSL_get_error(hctx->ssl, len))) {
2916         case SSL_ERROR_WANT_WRITE:
2917             con->is_writable = -1;
2918             __attribute_fallthrough__
2919         case SSL_ERROR_WANT_READ:
2920             con->is_readable = 0;
2921 
2922             /* the manual says we have to call SSL_read with the same arguments
2923              * next time.  we ignore this restriction; no one has complained
2924              * about it in 1.5 yet, so it probably works anyway.
2925              */
2926 
2927             return 0;
2928         case SSL_ERROR_SYSCALL:
2929             /**
2930              * man SSL_get_error()
2931              *
2932              * SSL_ERROR_SYSCALL
2933              *   Some I/O error occurred.  The OpenSSL error queue may contain
2934              *   more information on the error.  If the error queue is empty
2935              *   (i.e. ERR_get_error() returns 0), ret can be used to find out
2936              *   more about the error: If ret == 0, an EOF was observed that
2937              *   violates the protocol.  If ret == -1, the underlying BIO
2938              *   reported an I/O error (for socket I/O on Unix systems, consult
2939              *   errno for details).
2940              *
2941              */
2942             while((ssl_err = ERR_get_error())) {
2943                 /* get all errors from the error-queue */
2944                 log_error(hctx->errh, __FILE__, __LINE__,
2945                   "SSL: %d %s", rc, ERR_error_string(ssl_err, NULL));
2946             }
2947 
2948             switch(oerrno) {
2949             case ECONNRESET:
2950                 if (!hctx->conf.ssl_log_noise) break;
2951                 __attribute_fallthrough__
2952             default:
2953                 /* (oerrno should be something like ECONNABORTED not 0
2954                  *  if client disconnected before anything was sent
2955                  *  (e.g. TCP connection probe), but it does not appear
2956                  *  that openssl provides such notification, not even
2957                  *  something like SSL_R_SSL_HANDSHAKE_FAILURE) */
2958                 if (0==oerrno && 0==cq->bytes_in && !hctx->conf.ssl_log_noise)
2959                     break;
2960 
2961                 errno = oerrno; /*(for log_perror())*/
2962                 log_perror(hctx->errh, __FILE__, __LINE__,
2963                   "SSL: %d %d %d", len, rc, oerrno);
2964                 break;
2965             }
2966 
2967             break;
2968         case SSL_ERROR_ZERO_RETURN:
2969             /* clean shutdown on the remote side */
2970 
2971             if (rc == 0) {
2972                 /* FIXME: later */
2973             }
2974 
2975             __attribute_fallthrough__
2976         default:
2977             while((ssl_err = ERR_get_error())) {
2978                 switch (ERR_GET_REASON(ssl_err)) {
2979                 case SSL_R_SSL_HANDSHAKE_FAILURE:
2980               #ifdef SSL_R_UNEXPECTED_EOF_WHILE_READING
2981                 case SSL_R_UNEXPECTED_EOF_WHILE_READING:
2982               #endif
2983               #ifdef SSL_R_TLSV1_ALERT_UNKNOWN_CA
2984                 case SSL_R_TLSV1_ALERT_UNKNOWN_CA:
2985               #endif
2986               #ifdef SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN
2987                 case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:
2988               #endif
2989               #ifdef SSL_R_SSLV3_ALERT_BAD_CERTIFICATE
2990                 case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:
2991               #endif
2992                     if (!hctx->conf.ssl_log_noise) continue;
2993                     break;
2994                 default:
2995                     break;
2996                 }
2997                 /* get all errors from the error-queue */
2998                 log_error(hctx->errh, __FILE__, __LINE__,
2999                   "SSL: %d %s", rc, ERR_error_string(ssl_err, NULL));
3000             }
3001             break;
3002         }
3003         return -1;
3004     } else if (len == 0) {
3005         con->is_readable = 0;
3006         /* the other end close the connection -> KEEP-ALIVE */
3007 
3008         return -2;
3009     } else {
3010         return 0;
3011     }
3012 }
3013 
3014 
3015 CONNECTION_FUNC(mod_openssl_handle_con_accept)
3016 {
3017     const server_socket *srv_sock = con->srv_socket;
3018     if (!srv_sock->is_ssl) return HANDLER_GO_ON;
3019 
3020     plugin_data *p = p_d;
3021     handler_ctx * const hctx = handler_ctx_init();
3022     request_st * const r = &con->request;
3023     hctx->r = r;
3024     hctx->con = con;
3025     hctx->tmp_buf = con->srv->tmp_buf;
3026     hctx->errh = r->conf.errh;
3027     con->plugin_ctx[p->id] = hctx;
3028     buffer_blank(&r->uri.authority);
3029 
3030     plugin_ssl_ctx * const s = p->ssl_ctxs + srv_sock->sidx;
3031     hctx->ssl = SSL_new(s->ssl_ctx);
3032     if (NULL != hctx->ssl
3033         && SSL_set_app_data(hctx->ssl, hctx)
3034         && SSL_set_fd(hctx->ssl, con->fd)) {
3035         SSL_set_accept_state(hctx->ssl);
3036         con->network_read = connection_read_cq_ssl;
3037         con->network_write = connection_write_cq_ssl;
3038         con->proto_default_port = 443; /* "https" */
3039         mod_openssl_patch_config(r, &hctx->conf);
3040         return HANDLER_GO_ON;
3041     }
3042     else {
3043         log_error(r->conf.errh, __FILE__, __LINE__,
3044           "SSL: %s", ERR_error_string(ERR_get_error(), NULL));
3045         return HANDLER_ERROR;
3046     }
3047 }
3048 
3049 
3050 static void
3051 mod_openssl_detach(handler_ctx *hctx)
3052 {
3053     /* step aside from further SSL processing
3054      * (used after handle_connection_shut_wr hook) */
3055     /* future: might restore prior network_read and network_write fn ptrs */
3056     hctx->con->is_ssl_sock = 0;
3057     /* if called after handle_connection_shut_wr hook, shutdown SHUT_WR */
3058     if (-1 == hctx->close_notify) shutdown(hctx->con->fd, SHUT_WR);
3059     hctx->close_notify = 1;
3060 }
3061 
3062 
3063 CONNECTION_FUNC(mod_openssl_handle_con_shut_wr)
3064 {
3065     plugin_data *p = p_d;
3066     handler_ctx *hctx = con->plugin_ctx[p->id];
3067     if (NULL == hctx) return HANDLER_GO_ON;
3068 
3069     hctx->close_notify = -2;
3070     if (SSL_is_init_finished(hctx->ssl)) {
3071         mod_openssl_close_notify(hctx);
3072     }
3073     else {
3074         mod_openssl_detach(hctx);
3075     }
3076 
3077     return HANDLER_GO_ON;
3078 }
3079 
3080 
3081 static int
3082 mod_openssl_close_notify(handler_ctx *hctx)
3083 {
3084         int ret, ssl_r;
3085         unsigned long err;
3086         log_error_st *errh;
3087 
3088         if (1 == hctx->close_notify) return -2;
3089 
3090         ERR_clear_error();
3091         switch ((ret = SSL_shutdown(hctx->ssl))) {
3092         case 1:
3093             mod_openssl_detach(hctx);
3094             return -2;
3095         case 0:
3096             /* Drain SSL read buffers in case pending records need processing.
3097              * Limit to reading next record to avoid denial of service when CPU
3098              * processing TLS is slower than arrival speed of TLS data packets.
3099              * (unless hctx->conf.ssl_read_ahead is set)
3100              *
3101              * references:
3102              *
3103              * "New session ticket breaks bidirectional shutdown of TLS 1.3 connection"
3104              * https://github.com/openssl/openssl/issues/6262
3105              *
3106              * The peer is still allowed to send data after receiving the
3107              * "close notify" event. If the peer did send data it need to be
3108              * processed by calling SSL_read() before calling SSL_shutdown() a
3109              * second time. SSL_read() will indicate the end of the peer data by
3110              * returning <= 0 and SSL_get_error() returning
3111              * SSL_ERROR_ZERO_RETURN. It is recommended to call SSL_read()
3112              * between SSL_shutdown() calls.
3113              *
3114              * Additional discussion in "Auto retry in shutdown"
3115              * https://github.com/openssl/openssl/pull/6340
3116              */
3117             ssl_r = SSL_pending(hctx->ssl);
3118             if (ssl_r) {
3119                 do {
3120                     char buf[4096];
3121                     ret = SSL_read(hctx->ssl, buf, (int)sizeof(buf));
3122                 } while (ret > 0 && (hctx->conf.ssl_read_ahead||(ssl_r-=ret)));
3123             }
3124 
3125             ERR_clear_error();
3126             switch ((ret = SSL_shutdown(hctx->ssl))) {
3127             case 1:
3128                 mod_openssl_detach(hctx);
3129                 return -2;
3130             case 0:
3131                 hctx->close_notify = -1;
3132                 return 0;
3133             default:
3134                 break;
3135             }
3136 
3137             __attribute_fallthrough__
3138         default:
3139 
3140             if (!SSL_is_init_finished(hctx->ssl)) {
3141                 mod_openssl_detach(hctx);
3142                 return -2;
3143             }
3144 
3145             switch ((ssl_r = SSL_get_error(hctx->ssl, ret))) {
3146             case SSL_ERROR_ZERO_RETURN:
3147             case SSL_ERROR_WANT_WRITE:
3148             case SSL_ERROR_WANT_READ:
3149                 hctx->close_notify = -1;
3150                 return 0; /* try again later */
3151             case SSL_ERROR_SYSCALL:
3152                 /* perhaps we have error waiting in our error-queue */
3153                 errh = hctx->r->conf.errh;
3154                 if (0 != (err = ERR_get_error())) {
3155                     do {
3156                         log_error(errh, __FILE__, __LINE__,
3157                           "SSL: %d %d %s",ssl_r,ret,ERR_error_string(err,NULL));
3158                     } while((err = ERR_get_error()));
3159                 } else if (errno != 0) {
3160                     /*ssl bug (see lighttpd ticket #2213): sometimes errno==0*/
3161                     switch(errno) {
3162                     case EPIPE:
3163                     case ECONNRESET:
3164                         break;
3165                     default:
3166                         log_perror(errh, __FILE__, __LINE__,
3167                           "SSL (error): %d %d", ssl_r, ret);
3168                         break;
3169                     }
3170                 }
3171 
3172                 break;
3173             default:
3174                 errh = hctx->r->conf.errh;
3175                 while((err = ERR_get_error())) {
3176                     log_error(errh, __FILE__, __LINE__,
3177                       "SSL: %d %d %s", ssl_r, ret, ERR_error_string(err, NULL));
3178                 }
3179 
3180                 break;
3181             }
3182         }
3183         ERR_clear_error();
3184         hctx->close_notify = -1;
3185         return ret;
3186 }
3187 
3188 
3189 CONNECTION_FUNC(mod_openssl_handle_con_close)
3190 {
3191     plugin_data *p = p_d;
3192     handler_ctx *hctx = con->plugin_ctx[p->id];
3193     if (NULL != hctx) {
3194         con->plugin_ctx[p->id] = NULL;
3195         handler_ctx_free(hctx);
3196     }
3197 
3198     return HANDLER_GO_ON;
3199 }
3200 
3201 
3202 #ifndef OBJ_nid2sn
3203 #define OBJ_nid2sn  wolfSSL_OBJ_nid2sn
3204 #endif
3205 #ifndef OBJ_obj2nid
3206 #define OBJ_obj2nid wolfSSL_OBJ_obj2nid
3207 #endif
3208 #include <wolfssl/wolfcrypt/asn_public.h>
3209 
3210 
3211 static void
3212 https_add_ssl_client_subject (request_st * const r, X509_NAME *xn)
3213 {
3214     const size_t prelen = sizeof("SSL_CLIENT_S_DN_")-1;
3215     char key[64] = "SSL_CLIENT_S_DN_";
3216     for (int i = 0, nentries = X509_NAME_entry_count(xn); i < nentries; ++i) {
3217         int xobjnid;
3218         const char * xobjsn;
3219         X509_NAME_ENTRY *xe;
3220 
3221         if (!(xe = wolfSSL_X509_NAME_get_entry(xn, i))) {
3222             continue;
3223         }
3224         xobjnid = OBJ_obj2nid((ASN1_OBJECT*)X509_NAME_ENTRY_get_object(xe));
3225         xobjsn = OBJ_nid2sn(xobjnid);
3226         if (xobjsn) {
3227             const size_t len = strlen(xobjsn);
3228             if (prelen+len >= sizeof(key)) continue;
3229             memcpy(key+prelen, xobjsn, len); /*(not '\0'-terminated)*/
3230             http_header_env_set(r, key, prelen+len,
3231                                 (const char*)X509_NAME_ENTRY_get_data(xe)->data,
3232                                 X509_NAME_ENTRY_get_data(xe)->length);
3233         }
3234     }
3235 }
3236 
3237 
3238 __attribute_cold__
3239 static void
3240 https_add_ssl_client_verify_err (buffer * const b, long status)
3241 {
3242     char errstr[256];
3243     ERR_error_string_n(status, errstr, sizeof(errstr));
3244     buffer_append_string(b, errstr);
3245 }
3246 
3247 
3248 __attribute_noinline__
3249 static void
3250 https_add_ssl_client_entries (request_st * const r, handler_ctx * const hctx)
3251 {
3252     X509 *xs;
3253     X509_NAME *xn;
3254     buffer *vb = http_header_env_set_ptr(r, CONST_STR_LEN("SSL_CLIENT_VERIFY"));
3255 
3256     long vr = SSL_get_verify_result(hctx->ssl);
3257     if (vr != X509_V_OK) {
3258         buffer_copy_string_len(vb, CONST_STR_LEN("FAILED:"));
3259         https_add_ssl_client_verify_err(vb, vr);
3260         return;
3261     } else if (!(xs = SSL_get_peer_certificate(hctx->ssl))) {
3262         buffer_copy_string_len(vb, CONST_STR_LEN("NONE"));
3263         return;
3264     } else {
3265         buffer_copy_string_len(vb, CONST_STR_LEN("SUCCESS"));
3266     }
3267 
3268     xn = X509_get_subject_name(xs);
3269     {
3270         char buf[256];
3271         int len = safer_X509_NAME_oneline(xn, buf, sizeof(buf));
3272         if (len > 0) {
3273             if (len >= (int)sizeof(buf)) len = (int)sizeof(buf)-1;
3274             http_header_env_set(r,
3275                                 CONST_STR_LEN("SSL_CLIENT_S_DN"),
3276                                 buf, (size_t)len);
3277         }
3278     }
3279 
3280     https_add_ssl_client_subject(r, xn);
3281 
3282     {
3283         byte buf[64];
3284         int bsz = (int)sizeof(buf);
3285         if (wolfSSL_X509_get_serial_number(xs, buf, &bsz) == WOLFSSL_SUCCESS) {
3286             buffer_append_string_encoded_hex_uc(
3287               http_header_env_set_ptr(r, CONST_STR_LEN("SSL_CLIENT_M_SERIAL")),
3288               (char *)buf, (size_t)bsz);
3289         }
3290     }
3291 
3292     if (hctx->conf.ssl_verifyclient_username) {
3293         /* pick one of the exported values as "REMOTE_USER", for example
3294          *   ssl.verifyclient.username = "SSL_CLIENT_S_DN_UID"
3295          * or
3296          *   ssl.verifyclient.username = "SSL_CLIENT_S_DN_emailAddress"
3297          */
3298         const buffer *varname = hctx->conf.ssl_verifyclient_username;
3299         vb = http_header_env_get(r, BUF_PTR_LEN(varname));
3300         if (vb) { /* same as mod_auth_api.c:http_auth_setenv() */
3301             http_header_env_set(r,
3302                                 CONST_STR_LEN("REMOTE_USER"),
3303                                 BUF_PTR_LEN(vb));
3304             http_header_env_set(r,
3305                                 CONST_STR_LEN("AUTH_TYPE"),
3306                                 CONST_STR_LEN("SSL_CLIENT_VERIFY"));
3307         }
3308     }
3309 
3310     if (hctx->conf.ssl_verifyclient_export_cert) {
3311         int dersz, pemsz;
3312         const unsigned char *der = wolfSSL_X509_get_der(xs, &dersz);
3313         pemsz = der ? wc_DerToPemEx(der, dersz, NULL, 0, NULL, CERT_TYPE) : 0;
3314         if (pemsz > 0) {
3315             vb = http_header_env_set_ptr(r, CONST_STR_LEN("SSL_CLIENT_CERT"));
3316             if (0 == wc_DerToPemEx(der, dersz,
3317                                    (byte *)buffer_string_prepare_copy(vb,pemsz),
3318                                    pemsz, NULL, CERT_TYPE))
3319                 buffer_commit(vb, (uint32_t)pemsz);
3320         }
3321     }
3322     X509_free(xs);
3323 }
3324 
3325 
3326 static void
3327 http_cgi_ssl_env (request_st * const r, handler_ctx * const hctx)
3328 {
3329     const char *s;
3330     const SSL_CIPHER *cipher;
3331 
3332     s = SSL_get_version(hctx->ssl);
3333     http_header_env_set(r, CONST_STR_LEN("SSL_PROTOCOL"), s, strlen(s));
3334 
3335     if ((cipher = SSL_get_current_cipher(hctx->ssl))) {
3336         s = SSL_CIPHER_get_name(cipher);
3337         http_header_env_set(r, CONST_STR_LEN("SSL_CIPHER"), s, strlen(s));
3338         /*(wolfSSL preprocessor defines are obnoxious)*/
3339       #if defined(OPENSSL_ALL) \
3340        || (defined(OPENSSL_EXTRA) \
3341            && (defined(HAVE_STUNNEL)    || \
3342                defined(WOLFSSL_NGINX)   || defined(HAVE_LIGHTY) || \
3343                defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH)))
3344         int usekeysize, algkeysize = 0;
3345         char buf[LI_ITOSTRING_LENGTH];
3346         usekeysize = wolfSSL_CIPHER_get_bits(cipher, &algkeysize);
3347         if (0 == algkeysize) algkeysize = usekeysize;
3348         http_header_env_set(r, CONST_STR_LEN("SSL_CIPHER_USEKEYSIZE"),
3349                             buf, li_itostrn(buf, sizeof(buf), usekeysize));
3350         http_header_env_set(r, CONST_STR_LEN("SSL_CIPHER_ALGKEYSIZE"),
3351                             buf, li_itostrn(buf, sizeof(buf), algkeysize));
3352       #endif
3353     }
3354 }
3355 
3356 
3357 REQUEST_FUNC(mod_openssl_handle_request_env)
3358 {
3359     plugin_data *p = p_d;
3360     /* simple flag for request_env_patched */
3361     if (r->plugin_ctx[p->id]) return HANDLER_GO_ON;
3362     handler_ctx *hctx = r->con->plugin_ctx[p->id];
3363     if (NULL == hctx) return HANDLER_GO_ON;
3364     r->plugin_ctx[p->id] = (void *)(uintptr_t)1u;
3365 
3366     http_cgi_ssl_env(r, hctx);
3367     if (hctx->conf.ssl_verifyclient) {
3368         https_add_ssl_client_entries(r, hctx);
3369     }
3370 
3371     return HANDLER_GO_ON;
3372 }
3373 
3374 
3375 REQUEST_FUNC(mod_openssl_handle_uri_raw)
3376 {
3377     /* mod_openssl must be loaded prior to mod_auth
3378      * if mod_openssl is configured to set REMOTE_USER based on client cert */
3379     /* mod_openssl must be loaded after mod_extforward
3380      * if mod_openssl config is based on lighttpd.conf remote IP conditional
3381      * using remote IP address set by mod_extforward, *unless* PROXY protocol
3382      * is enabled with extforward.hap-PROXY = "enable", in which case the
3383      * reverse is true: mod_extforward must be loaded after mod_openssl */
3384     plugin_data *p = p_d;
3385     handler_ctx *hctx = r->con->plugin_ctx[p->id];
3386     if (NULL == hctx) return HANDLER_GO_ON;
3387 
3388     mod_openssl_patch_config(r, &hctx->conf);
3389     if (hctx->conf.ssl_verifyclient) {
3390         mod_openssl_handle_request_env(r, p);
3391     }
3392 
3393     return HANDLER_GO_ON;
3394 }
3395 
3396 
3397 REQUEST_FUNC(mod_openssl_handle_request_reset)
3398 {
3399     plugin_data *p = p_d;
3400     r->plugin_ctx[p->id] = NULL; /* simple flag for request_env_patched */
3401     return HANDLER_GO_ON;
3402 }
3403 
3404 
3405 TRIGGER_FUNC(mod_openssl_handle_trigger) {
3406     const plugin_data * const p = p_d;
3407     const unix_time64_t cur_ts = log_epoch_secs;
3408     if (cur_ts & 0x3f) return HANDLER_GO_ON; /*(continue once each 64 sec)*/
3409     UNUSED(srv);
3410     UNUSED(p);
3411 
3412   #ifdef HAVE_SESSION_TICKET
3413     mod_openssl_session_ticket_key_check(p, cur_ts);
3414   #endif
3415 
3416   #ifdef HAVE_OCSP
3417     mod_openssl_refresh_stapling_files(srv, p, cur_ts);
3418   #endif
3419 
3420     return HANDLER_GO_ON;
3421 }
3422 
3423 
3424 int mod_wolfssl_plugin_init (plugin *p);
3425 int mod_wolfssl_plugin_init (plugin *p)
3426 {
3427     p->version      = LIGHTTPD_VERSION_ID;
3428     p->name         = "wolfssl";
3429     p->init         = mod_openssl_init;
3430     p->cleanup      = mod_openssl_free;
3431     p->priv_defaults= mod_openssl_set_defaults;
3432 
3433     p->handle_connection_accept  = mod_openssl_handle_con_accept;
3434     p->handle_connection_shut_wr = mod_openssl_handle_con_shut_wr;
3435     p->handle_connection_close   = mod_openssl_handle_con_close;
3436     p->handle_uri_raw            = mod_openssl_handle_uri_raw;
3437     p->handle_request_env        = mod_openssl_handle_request_env;
3438     p->handle_request_reset      = mod_openssl_handle_request_reset;
3439     p->handle_trigger            = mod_openssl_handle_trigger;
3440 
3441     return 0;
3442 }
3443 
3444 
3445 static int
3446 mod_openssl_ssl_conf_proto_val (server *srv, plugin_config_socket *s, const buffer *b, int max)
3447 {
3448     if (NULL == b) /* default: min TLSv1.2, max TLSv1.3 */
3449         return max ? WOLFSSL_TLSV1_3 : WOLFSSL_TLSV1_2;
3450     else if (buffer_eq_icase_slen(b, CONST_STR_LEN("None"))) /*"disable" limit*/
3451         return max
3452           ? WOLFSSL_TLSV1_3
3453           : (s->ssl_use_sslv3 ? WOLFSSL_SSLV3 : WOLFSSL_TLSV1);
3454     else if (buffer_eq_icase_slen(b, CONST_STR_LEN("SSLv3")))
3455         return WOLFSSL_SSLV3;
3456     else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.0")))
3457         return WOLFSSL_TLSV1;
3458     else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.1")))
3459         return WOLFSSL_TLSV1_1;
3460     else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.2")))
3461         return WOLFSSL_TLSV1_2;
3462     else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.3")))
3463         return WOLFSSL_TLSV1_3;
3464     else {
3465         if (buffer_eq_icase_slen(b, CONST_STR_LEN("DTLSv1"))
3466             || buffer_eq_icase_slen(b, CONST_STR_LEN("DTLSv1.2")))
3467             log_error(srv->errh, __FILE__, __LINE__,
3468                       "SSL: ssl.openssl.ssl-conf-cmd %s %s ignored",
3469                       max ? "MaxProtocol" : "MinProtocol", b->ptr);
3470         else
3471             log_error(srv->errh, __FILE__, __LINE__,
3472                       "SSL: ssl.openssl.ssl-conf-cmd %s %s invalid; ignored",
3473                       max ? "MaxProtocol" : "MinProtocol", b->ptr);
3474     }
3475     return max ? WOLFSSL_TLSV1_3 : WOLFSSL_TLSV1_2;
3476 }
3477 
3478 
3479 static int
3480 mod_openssl_ssl_conf_cmd (server *srv, plugin_config_socket *s)
3481 {
3482     /* reference:
3483      * https://www.openssl.org/docs/man1.1.1/man3/SSL_CONF_cmd.html */
3484     int rc = 0;
3485     buffer *cipherstring = NULL;
3486     /*buffer *ciphersuites = NULL;*/
3487     buffer *minb = NULL;
3488     buffer *maxb = NULL;
3489     buffer *curves = NULL;
3490 
3491     for (size_t i = 0; i < s->ssl_conf_cmd->used; ++i) {
3492         data_string *ds = (data_string *)s->ssl_conf_cmd->data[i];
3493         if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("CipherString")))
3494             cipherstring = &ds->value;
3495       #if 0
3496         else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Ciphersuites")))
3497             ciphersuites = &ds->value;
3498       #endif
3499         else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Curves"))
3500               || buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Groups")))
3501             curves = &ds->value;
3502         else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("MaxProtocol")))
3503             maxb = &ds->value;
3504         else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("MinProtocol")))
3505             minb = &ds->value;
3506         else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Protocol"))) {
3507             /* openssl config for Protocol=... is complex and deprecated */
3508             log_error(srv->errh, __FILE__, __LINE__,
3509                       "SSL: ssl.openssl.ssl-conf-cmd %s ignored; "
3510                       "use MinProtocol=... and MaxProtocol=... instead",
3511                       ds->key.ptr);
3512         }
3513         else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Options"))) {
3514             for (char *v = ds->value.ptr, *e; *v; v = e) {
3515                 while (*v == ' ' || *v == '\t' || *v == ',') ++v;
3516                 int flag = 1;
3517                 if (*v == '-') {
3518                     flag = 0;
3519                     ++v;
3520                 }
3521                 for (e = v; light_isalpha(*e); ++e) ;
3522                 switch ((int)(e-v)) {
3523                   case 11:
3524                     if (buffer_eq_icase_ssn(v, "Compression", 11)) {
3525                         /* (force disabled, the default, if HTTP/2 enabled) */
3526                         if (srv->srvconf.h2proto)
3527                             flag = 0;
3528                         if (flag)
3529                             SSL_CTX_clear_options(s->ssl_ctx,
3530                                                   SSL_OP_NO_COMPRESSION);
3531                         else
3532                             SSL_CTX_set_options(s->ssl_ctx,
3533                                                 SSL_OP_NO_COMPRESSION);
3534                         continue;
3535                     }
3536                     break;
3537                   case 13:
3538                     if (buffer_eq_icase_ssn(v, "SessionTicket", 13)) {
3539                         if (flag)
3540                             SSL_CTX_clear_options(s->ssl_ctx,
3541                                                   SSL_OP_NO_TICKET);
3542                         else
3543                             SSL_CTX_set_options(s->ssl_ctx,
3544                                                 SSL_OP_NO_TICKET);
3545                         continue;
3546                     }
3547                     break;
3548                   case 16:
3549                     if (buffer_eq_icase_ssn(v, "ServerPreference", 16)) {
3550                         if (flag)
3551                             SSL_CTX_set_options(s->ssl_ctx,
3552                                                SSL_OP_CIPHER_SERVER_PREFERENCE);
3553                         else
3554                             SSL_CTX_clear_options(s->ssl_ctx,
3555                                                SSL_OP_CIPHER_SERVER_PREFERENCE);
3556                         s->ssl_honor_cipher_order = flag;
3557                         continue;
3558                     }
3559                     break;
3560                   default:
3561                     break;
3562                 }
3563                 /* warn if not explicitly handled or ignored above */
3564                 if (!flag) --v;
3565                 log_error(srv->errh, __FILE__, __LINE__,
3566                           "SSL: ssl.openssl.ssl-conf-cmd Options %.*s "
3567                           "ignored", (int)(e-v), v);
3568             }
3569         }
3570       #if 0
3571         else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("..."))) {
3572         }
3573       #endif
3574         else {
3575             /* warn if not explicitly handled or ignored above */
3576             log_error(srv->errh, __FILE__, __LINE__,
3577                       "SSL: ssl.openssl.ssl-conf-cmd %s ignored",
3578                       ds->key.ptr);
3579         }
3580 
3581     }
3582 
3583     if (minb) {
3584         int n = mod_openssl_ssl_conf_proto_val(srv, s, minb, 0);
3585         if (wolfSSL_CTX_SetMinVersion(s->ssl_ctx, n) != WOLFSSL_SUCCESS)
3586             rc = -1;
3587     }
3588 
3589     if (maxb) {
3590         /* WolfSSL max ver is set at WolfSSL compile-time */
3591       #if LIBWOLFSSL_VERSION_HEX >= 0x04002000
3592         /*(could use SSL_OP_NO_* before 4.2.0)*/
3593         /*(wolfSSL_CTX_set_max_proto_version() 4.6.0 uses different defines)*/
3594         int n = mod_openssl_ssl_conf_proto_val(srv, s, maxb, 1);
3595         switch (n) {
3596           case WOLFSSL_SSLV3:
3597             wolfSSL_CTX_set_options(s->ssl_ctx, WOLFSSL_OP_NO_TLSv1);
3598             __attribute_fallthrough__
3599           case WOLFSSL_TLSV1:
3600             wolfSSL_CTX_set_options(s->ssl_ctx, WOLFSSL_OP_NO_TLSv1_1);
3601             __attribute_fallthrough__
3602           case WOLFSSL_TLSV1_1:
3603             wolfSSL_CTX_set_options(s->ssl_ctx, WOLFSSL_OP_NO_TLSv1_2);
3604             __attribute_fallthrough__
3605           case WOLFSSL_TLSV1_2:
3606             wolfSSL_CTX_set_options(s->ssl_ctx, WOLFSSL_OP_NO_TLSv1_3);
3607             __attribute_fallthrough__
3608           case WOLFSSL_TLSV1_3:
3609           default:
3610             break;
3611         }
3612       #endif
3613     }
3614 
3615     if (cipherstring && !buffer_is_blank(cipherstring)) {
3616         /* Disable support for low encryption ciphers */
3617         buffer_append_string_len(cipherstring,
3618                                  CONST_STR_LEN(":!aNULL:!eNULL:!EXP"));
3619         if (SSL_CTX_set_cipher_list(s->ssl_ctx, cipherstring->ptr) != 1) {
3620             log_error(srv->errh, __FILE__, __LINE__,
3621               "SSL: %s", ERR_error_string(ERR_get_error(), NULL));
3622             rc = -1;
3623         }
3624 
3625         if (s->ssl_honor_cipher_order)
3626             SSL_CTX_set_options(s->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
3627     }
3628 
3629     if (curves && !buffer_is_blank(curves)) {
3630         if (!mod_openssl_ssl_conf_curves(srv, s, curves))
3631             rc = -1;
3632     }
3633 
3634     return rc;
3635 }
3636