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