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