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