Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package lighttpd for openSUSE:Factory 
checked in at 2023-10-31 20:25:56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/lighttpd (Old)
 and      /work/SRC/openSUSE:Factory/.lighttpd.new.17445 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "lighttpd"

Tue Oct 31 20:25:56 2023 rev:62 rq:1121373 version:1.4.73

Changes:
--------
--- /work/SRC/openSUSE:Factory/lighttpd/lighttpd.changes        2023-10-08 
12:23:05.224444980 +0200
+++ /work/SRC/openSUSE:Factory/.lighttpd.new.17445/lighttpd.changes     
2023-10-31 20:26:15.003152780 +0100
@@ -1,0 +2,7 @@
+Tue Oct 31 06:53:05 UTC 2023 - Andreas Stieger <[email protected]>
+
+- update to 1.4.73:
+  * CVE-2023-44487: HTTP/2 detect and log rapid reset attack
+    (boo#1216123)
+
+-------------------------------------------------------------------

Old:
----
  lighttpd-1.4.72.tar.xz
  lighttpd-1.4.72.tar.xz.asc

New:
----
  lighttpd-1.4.73.tar.xz
  lighttpd-1.4.73.tar.xz.asc

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ lighttpd.spec ++++++
--- /var/tmp/diff_new_pack.MXB2H7/_old  2023-10-31 20:26:15.819182753 +0100
+++ /var/tmp/diff_new_pack.MXB2H7/_new  2023-10-31 20:26:15.823182900 +0100
@@ -26,7 +26,7 @@
   %define _fillupdir %{_localstatedir}/adm/fillup-templates
 %endif
 Name:           lighttpd
-Version:        1.4.72
+Version:        1.4.73
 Release:        0
 Summary:        A Secure, Fast, Compliant, and Very Flexible Web Server
 License:        BSD-3-Clause

++++++ lighttpd-1.4.72.tar.xz -> lighttpd-1.4.73.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lighttpd-1.4.72/CMakeLists.txt 
new/lighttpd-1.4.73/CMakeLists.txt
--- old/lighttpd-1.4.72/CMakeLists.txt  2023-10-07 02:10:38.000000000 +0200
+++ new/lighttpd-1.4.73/CMakeLists.txt  2023-10-31 03:35:56.000000000 +0100
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.7.0 FATAL_ERROR)
 
-project(lighttpd VERSION 1.4.72 LANGUAGES C)
+project(lighttpd VERSION 1.4.73 LANGUAGES C)
 
 # use C11 with CMake >= 3.1
 set(CMAKE_C_STANDARD 11)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lighttpd-1.4.72/NEWS new/lighttpd-1.4.73/NEWS
--- old/lighttpd-1.4.72/NEWS    2023-10-07 02:10:38.000000000 +0200
+++ new/lighttpd-1.4.73/NEWS    2023-10-31 03:35:56.000000000 +0100
@@ -3,6 +3,34 @@
 NEWS
 ====
 
+- 1.4.73 - 2023-10-30
+  * [core] add .mkv to mimetype.assign builtin defaults
+  * [core] warn if out-of-range value for config short
+  * [mod_openssl] set default curves for ossl < 1.1.0
+  * [mod_h2] parse HEADERS flags sooner
+  * [mod_h2] check send window before defer frame rd
+  * [mod_h2] send GOAWAY to excessive request flood
+  * [mod_h2] h2_parse_headers_frame() adjust args
+  * [mod_h2] h2_recv_headers() parse trailers earlier
+  * [mod_h2] send GOAWAY to excessive request flood
+  * [mod_h2] discard new streams after GOAWAY sent
+  * [mod_h2] h2_discard_headers() to HPACK-decode hdrs
+  * [core] parse entire server.http-parseopts list
+  * [mod_wstunnel] Sec-WebSocket-Protocol only if req hdr
+  * [mod_h2] disable h2proto if mod_h2 was not found
+  * [core] omit dlopen trace for mod_h2, mod_deflate
+  * [mod_h2] defer input parsing if large output queue
+  * [mod_h2] defer frame handling if stream pend close
+  * [mod_h2] detect and log HTTP/2 rapid reset attack
+  * [core] honor MBEDTLS_USE_PSA_CRYPTO for hash,rand
+  * [mod_mbedtls] honor MBEDTLS_USE_PSA_CRYPTO for rand
+  * [core] comment out li_rand_bytes() (unused)
+  * [mod_mbedtls] handle mbedtls 3.x partial write
+  * [mod_h2] detect and log HTTP/2 rapid reset attack
+  * [mod_h2] detect and log HTTP/2 rapid reset attack
+  * [mod_openssl] warn if openssl version < 3.0.0
+  * [mod_openssl] include openssl/hmac.h for boringssl
+
 - 1.4.72 - 2023-10-06
   * [core] save config read from stdin across restart
   * [core] warn if daemonize w/o absolute config path
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lighttpd-1.4.72/SConstruct 
new/lighttpd-1.4.73/SConstruct
--- old/lighttpd-1.4.72/SConstruct      2023-10-07 02:10:38.000000000 +0200
+++ new/lighttpd-1.4.73/SConstruct      2023-10-31 03:35:56.000000000 +0100
@@ -12,7 +12,7 @@
        string_types = str
 
 package = 'lighttpd'
-version = '1.4.72'
+version = '1.4.73'
 
 underscorify_reg = re.compile('[^A-Z0-9]')
 def underscorify(id):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lighttpd-1.4.72/configure 
new/lighttpd-1.4.73/configure
--- old/lighttpd-1.4.72/configure       2023-10-07 02:10:58.000000000 +0200
+++ new/lighttpd-1.4.73/configure       2023-10-31 03:36:07.000000000 +0100
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.71 for lighttpd 1.4.72.
+# Generated by GNU Autoconf 2.71 for lighttpd 1.4.73.
 #
 # Report bugs to <https://redmine.lighttpd.net/projects/lighttpd/boards/2>.
 #
@@ -622,8 +622,8 @@
 # Identity of this package.
 PACKAGE_NAME='lighttpd'
 PACKAGE_TARNAME='lighttpd'
-PACKAGE_VERSION='1.4.72'
-PACKAGE_STRING='lighttpd 1.4.72'
+PACKAGE_VERSION='1.4.73'
+PACKAGE_STRING='lighttpd 1.4.73'
 PACKAGE_BUGREPORT='https://redmine.lighttpd.net/projects/lighttpd/boards/2'
 PACKAGE_URL='https://www.lighttpd.net/'
 
@@ -1527,7 +1527,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures lighttpd 1.4.72 to adapt to many kinds of systems.
+\`configure' configures lighttpd 1.4.73 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1598,7 +1598,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of lighttpd 1.4.72:";;
+     short | recursive ) echo "Configuration of lighttpd 1.4.73:";;
    esac
   cat <<\_ACEOF
 
@@ -1807,7 +1807,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-lighttpd configure 1.4.72
+lighttpd configure 1.4.73
 generated by GNU Autoconf 2.71
 
 Copyright (C) 2021 Free Software Foundation, Inc.
@@ -2223,7 +2223,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by lighttpd $as_me 1.4.72, which was
+It was created by lighttpd $as_me 1.4.73, which was
 generated by GNU Autoconf 2.71.  Invocation command line was
 
   $ $0$ac_configure_args_raw
@@ -3575,7 +3575,7 @@
 
 # Define the identity of the package.
  PACKAGE='lighttpd'
- VERSION='1.4.72'
+ VERSION='1.4.73'
 
 
 printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -21856,7 +21856,7 @@
   fi
 fi
 
-LIGHTTPD_VERSION_ID=0x10448
+LIGHTTPD_VERSION_ID=0x10449
 
 printf "%s\n" "#define LIGHTTPD_VERSION_ID $LIGHTTPD_VERSION_ID" >>confdefs.h
 
@@ -22454,7 +22454,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by lighttpd $as_me 1.4.72, which was
+This file was extended by lighttpd $as_me 1.4.73, which was
 generated by GNU Autoconf 2.71.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -22523,7 +22523,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-lighttpd config.status 1.4.72
+lighttpd config.status 1.4.73
 configured by $0, generated by GNU Autoconf 2.71,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lighttpd-1.4.72/configure.ac 
new/lighttpd-1.4.73/configure.ac
--- old/lighttpd-1.4.72/configure.ac    2023-10-07 02:10:38.000000000 +0200
+++ new/lighttpd-1.4.73/configure.ac    2023-10-31 03:35:56.000000000 +0100
@@ -14,7 +14,7 @@
 dnl   function call, the argument should be on different lines than the
 dnl   wrapping braces
 AC_PREREQ([2.60])
-AC_INIT([lighttpd],[1.4.72],[https://redmine.lighttpd.net/projects/lighttpd/boards/2],[lighttpd],[https://www.lighttpd.net/])
+AC_INIT([lighttpd],[1.4.73],[https://redmine.lighttpd.net/projects/lighttpd/boards/2],[lighttpd],[https://www.lighttpd.net/])
 AC_CONFIG_SRCDIR([src/server.c])
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_MACRO_DIR([m4])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lighttpd-1.4.72/meson.build 
new/lighttpd-1.4.73/meson.build
--- old/lighttpd-1.4.72/meson.build     2023-10-07 02:10:38.000000000 +0200
+++ new/lighttpd-1.4.73/meson.build     2023-10-31 03:35:56.000000000 +0100
@@ -1,7 +1,7 @@
 project(
   'lighttpd',
   'c',
-  version: '1.4.72',
+  version: '1.4.73',
   license: 'BSD-3-Clause',
   default_options: ['c_std=c11'],
   meson_version: '>=0.47.0',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lighttpd-1.4.72/src/configfile-glue.c 
new/lighttpd-1.4.73/src/configfile-glue.c
--- old/lighttpd-1.4.72/src/configfile-glue.c   2023-10-07 02:10:38.000000000 
+0200
+++ new/lighttpd-1.4.73/src/configfile-glue.c   2023-10-31 03:35:56.000000000 
+0100
@@ -197,10 +197,6 @@
             break;
           case T_CONFIG_SHORT:
             switch(du->type) {
-              case TYPE_INTEGER:
-                cpv->v.shrt =
-                  (unsigned short)((const data_integer *)du)->value;
-                break;
               case TYPE_STRING: {
                 /* If the value came from an environment variable, then it is
                  * a data_string, although it may contain a number in ASCII
@@ -218,10 +214,17 @@
                     }
                 }
                 log_error(srv->errh, __FILE__, __LINE__,
-                  "got a string but expected a short: %s %s", cpk[i].k, v);
+                  "got a string but expected a short integer: %s %s", 
cpk[i].k, v);
                 rc = 0;
                 continue;
               }
+              case TYPE_INTEGER:
+                cpv->v.shrt =
+                  (unsigned short)((const data_integer *)du)->value;
+                if (((const data_integer *)du)->value >= 0
+                    && ((const data_integer *)du)->value <= 65535)
+                    break;
+                __attribute_fallthrough__
               default:
                 log_error(srv->errh, __FILE__, __LINE__,
                   "unexpected type for key: %s %d expected a short integer, "
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lighttpd-1.4.72/src/configfile.c 
new/lighttpd-1.4.73/src/configfile.c
--- old/lighttpd-1.4.72/src/configfile.c        2023-10-07 02:10:38.000000000 
+0200
+++ new/lighttpd-1.4.73/src/configfile.c        2023-10-31 03:35:56.000000000 
+0100
@@ -554,7 +554,8 @@
 
 static int config_http_parseopts (server *srv, const array *a) {
     unsigned short int opts = srv->srvconf.http_url_normalize;
-    unsigned short int decode_2f = 1;
+    uint8_t decode_2f = 1;
+    uint8_t url_normalize = 1;
     int rc = 1;
     for (size_t i = 0; i < a->used; ++i) {
         const data_string * const ds = (const data_string *)a->data[i];
@@ -616,14 +617,15 @@
         else {
             opts &= ~opt;
             if (opt == HTTP_PARSEOPT_URL_NORMALIZE) {
-                opts = 0;
-                break;
+                url_normalize = 0;
             }
             if (opt == HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_DECODE) {
                 decode_2f = 0;
             }
         }
     }
+    if (!url_normalize)
+        opts = 0;
     if (opts != 0) {
         opts |= HTTP_PARSEOPT_URL_NORMALIZE;
         if ((opts & (HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_DECODE
@@ -992,6 +994,7 @@
        ,".webp",  "image/webp"
 
        ,".avi",   "video/x-msvideo"
+       ,".mkv",   "video/x-matroska"
        ,".m4v",   "video/mp4"
        ,".mp4",   "video/mp4"
        ,".mpeg",  "video/mpeg"
@@ -1367,6 +1370,9 @@
         config_feature_bool(srv, "server.metrics-high-precision",
                             srv->srvconf.high_precision_timestamps);
 
+    /* disable h2proto if mod_h2 was not found during plugin load */
+    p->defaults.h2proto = srv->srvconf.h2proto;
+
     /* configure default server_tag if not set
      * (if configured to blank, unset server_tag)*/
     if (!p->defaults.server_tag)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lighttpd-1.4.72/src/h2.c new/lighttpd-1.4.73/src/h2.c
--- old/lighttpd-1.4.72/src/h2.c        2023-10-07 02:10:38.000000000 +0200
+++ new/lighttpd-1.4.73/src/h2.c        2023-10-31 03:35:56.000000000 +0100
@@ -435,6 +435,22 @@
 {
     h2con * const h2c = (h2con *)con->hx;
 
+    /* avoid sending REFUSED_STREAM if an existing stream is ready to be
+     * cleaned up, better handling edge case where stream concurrency limit
+     * has been reached and client sends RST_STREAM followed by HEADERS to
+     * cancel an existing stream and create a new, different stream.
+     * Note: this handles HTTP/2 rapid reset attack (CVE-2023-44487)
+     * slightly better than prior behavior by avoiding the minor overhead
+     * of responding with RST_STREAM REFUSED_STREAM */
+    for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
+        const request_st * const r = h2c->r[i];
+        if (r->state > CON_STATE_WRITE)
+            /* (CON_STATE_RESPONSE_END or CON_STATE_ERROR)
+             * request will be cleaned up shortly, releasing a slot;
+             * defer processing frame rather than sending REFUSED_STREAM */
+            return -1;
+    }
+
     if (h2c->sent_settings) { /*(see h2_recv_settings() comments)*/
         /* client connected and immediately sent flurry of request streams
          * (h2c->sent_settings is non-zero if sent SETTINGS frame to
@@ -443,13 +459,31 @@
          * server Connection Preface, so a well-behaved client will
          * adjust after it sends its initial requests.
          *   (e.g. h2load -n 100 -m 100 sends 100 requests upon connect)
-         *
+         */
+
+        /* Send GOAWAY if too many requests (> 100) sent prior to SETTINGS ackn
+         *   (and if we reach here checking to refuse excess stream).
+         * (lighttpd currently sends SETTINGS once, following server preface) 
*/
+        if (h2id > 200) {
+            log_error(NULL, __FILE__, __LINE__,
+              "h2: %s too many refused requests before SETTINGS ackn",
+              con->request.dst_addr_buf->ptr);
+            h2_send_goaway_e(con, H2_E_ENHANCE_YOUR_CALM);
+            return 0;
+        }
+
+        /*
          * Check if active streams have pending request body.  If all active
          * streams have pending request body, then must refuse new stream as
          * progress might be blocked if active streams all wait for DATA. */
         for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
             const request_st * const r = h2c->r[i];
             if (r->reqbody_length == r->reqbody_queue.bytes_in) {
+                /* check that stream response will not be blocked waiting
+                 * for stream WINDOW_UPDATE or connection WINDOW_UPDATE */
+                request_st * const h2r = &con->request;
+                if (r->x.h2.swin <= 0 || h2r->x.h2.swin <= 0) continue;
+
                 /* no pending request body; at least this request may proceed,
                  * though others waiting for request body may block until new
                  * request streams become active if new request streams precede
@@ -472,6 +506,30 @@
     /* too many active streams; refuse new stream */
     h2c->h2_cid = h2id;
     h2_send_rst_stream_id(h2id, con, H2_E_REFUSED_STREAM);
+
+    /* mitigate request floods pipelining streams in excess of concurrency 
limit
+     *
+     * excess streams opened after SETTINGS_MAX_CONCURRENT_STREAMS 8 sent may
+     * indicate an attack, or may indicate an impatient and ill-behaved client
+     * (SETTINGS_MAX_CONCURRENT_STREAMS >= 100 recommended by RFC 9113)
+     * If client sends more than 100 requests before sending SETTINGS ackn,
+     * then lighttpd treats that as excessive (above).  It could be accidental,
+     * but could be malicious since an attacker might intentionally omit 
sending
+     * SETTINGS ackn.  Note: SETTINGS_MAX_CONCURRENT_STREAMS is not currently
+     * sent by lighttpd after SETTINGS following HTTP/2 server preface, so this
+     * stream concurrency limit does not change after connection initiation.
+     * Here, either SETTINGS ackn has been received, and still too many 
requests
+     * (more than concurrenty limit of 8) *or* fall through from above if 
active
+     *  requests might block/timeout waiting for later frames).  Well-behaved
+     * clients should not fall afoul of server 
SETTINGS_MAX_CONCURRENT_STREAMS*/
+    if (++h2c->n_refused_stream > 16) {
+        log_error(NULL, __FILE__, __LINE__,
+          "h2: %s too many refused requests",
+          con->request.dst_addr_buf->ptr);
+        h2_send_goaway_e(con, H2_E_NO_ERROR);
+        /*(return 0 if sending H2_E_ENHANCE_YOUR_CALM instead)*/
+    }
+
     return 1;
 }
 
@@ -537,6 +595,27 @@
         /* XXX: ? add debug trace including error code from RST_STREAM ? */
         r->state = CON_STATE_ERROR;
         r->x.h2.state = H2_STATE_CLOSED;
+
+        /* attempt to detect HTTP/2 rapid reset attack (CVE-2023-44487)
+         * Send GOAWAY if 17 or more requests in recent batch of up to 32
+         * requests have been cancelled by client sending RST_STREAM.
+         * Note: this can legitimately occur, but is less likely for RST_STREAM
+         * in < 2 secs in which request was sent, repeated 16 more times within
+         * the next 32 requests, w/ SETTINGS_MAX_CONCURRENT_STREAMS only 8.
+         * Still, send GOAWAY NO_ERROR instead of sending ENHANCE_YOUR_CALM. */
+        if (!h2c->sent_goaway && r->start_hp.tv_sec+2 > log_epoch_secs) {
+            if ((++h2c->n_recv_rst_stream & 0xf) == 0)
+                h2c->n_recv_rst_stream |= 0xf;
+            uint8_t n_recv_rst_stream =
+              (h2c->n_recv_rst_stream >> 4) + (h2c->n_recv_rst_stream & 0xf);
+            if (n_recv_rst_stream > 16) {
+                log_error(NULL, __FILE__, __LINE__,
+                  "h2: %s sent too many RST_STREAM too quickly",
+                  con->request.dst_addr_buf->ptr);
+                h2_send_goaway_e(con, H2_E_NO_ERROR);
+            }
+        }
+
         return;
     }
     /* unknown/inactive stream id
@@ -1392,6 +1471,11 @@
      * be optional, like in HTTP/1.1 */
     request_st * const r = h2_get_stream_req(h2c, id);
     if (NULL == r) {
+        /* Note: sending GOAWAY here might be too strict.  With the 
introduction
+         * of h2_discard_headers(), the GOAWAY can now safely be commented out
+         * if this causes any issue with legitimate use in the field due to
+         * lighttpd responding to a stream, closing and forgetting about the
+         * stream, and then receiving trailers from the client for the 
stream.*/
         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
         return NULL;
     }
@@ -1413,15 +1497,42 @@
 }
 
 
+__attribute_cold__
+static void
+h2_discard_headers_frame (struct lshpack_dec * const restrict decoder, const 
unsigned char **psrc, const unsigned char * const restrict endp, const 
request_st * const restrict r)
+{
+    /* HPACK decode and discard; stripped down from h2_parse_headers_frame().
+     * If HEADERS frame is received, HEADERS frame must be HPACK-decoded to
+     * maintain HPACK decoder state consistency for the connection, unless
+     * GOAWAY has been sent and no new streams will be opened.  Even then,
+     * if GOAWAY was sent with H2_E_NO_ERROR, there is still chance that
+     * trailers sent later on active streams will fail to be decoded unless
+     * all HEADERS frames are HPACK-decoded in the order received. */
+
+    /*(h2_init_con() resized h2r->tmp_buf to 64k; shared with r->tmp_buf)*/
+    buffer * const tb = r->tmp_buf;
+    char * const tbptr = tb->ptr;
+    const lsxpack_strlen_t tbsz = (tb->size <= LSXPACK_MAX_STRLEN)
+      ? tb->size
+      : LSXPACK_MAX_STRLEN;
+
+    lsxpack_header_t lsx;
+    while (*psrc < endp) {
+        memset(&lsx, 0, sizeof(lsxpack_header_t));
+        lsx.buf = tbptr;
+        lsx.val_len = tbsz;
+        if (lshpack_dec_decode(decoder, psrc, endp, &lsx) != LSHPACK_OK)
+            break; /* HPACK decode failed; should probably send GOAWAY? */
+    }
+}
+
+
 static void h2_retire_stream (request_st *r, connection * const con);
 
 
 static void
-h2_parse_headers_frame (request_st * const restrict r, const unsigned char 
*psrc, const uint32_t plen, const int trailers)
+h2_parse_headers_frame (struct lshpack_dec * const restrict decoder, const 
unsigned char **psrc, const unsigned char * const endp, request_st * const 
restrict r, const int trailers)
 {
-    h2con * const h2c = (h2con *)r->con->hx;
-    struct lshpack_dec * const restrict decoder = &h2c->decoder;
-    const unsigned char * const endp = psrc + plen;
     http_header_parse_ctx hpctx;
     hpctx.hlen     = 0;
     hpctx.pseudo   = 1; /*(XXX: should be !trailers if handling trailers)*/
@@ -1442,11 +1553,11 @@
       : LSXPACK_MAX_STRLEN;
 
     lsxpack_header_t lsx;
-    while (psrc < endp) {
+    while (*psrc < endp) {
         memset(&lsx, 0, sizeof(lsxpack_header_t));
         lsx.buf = tbptr;
         lsx.val_len = tbsz;
-        rc = lshpack_dec_decode(decoder, &psrc, endp, &lsx);
+        rc = lshpack_dec_decode(decoder, psrc, endp, &lsx);
         if (0 == lsx.name_len)
             rc = LSHPACK_ERR_BAD_DATA;
         if (__builtin_expect( (rc == LSHPACK_OK), 1)) {
@@ -1466,6 +1577,9 @@
             if (__builtin_expect( (0 != http_status), 0)) {
                 if (r->http_status == 0) /*might be set if processing 
trailers*/
                     r->http_status = http_status;
+                /* Note: hpctx.hlen is not adjusted for rest of headers, nor
+                 * debug printing of headers if hpctx.log_request_header */
+                h2_discard_headers_frame(decoder, psrc, endp, r);
                 break;
             }
         }
@@ -1495,19 +1609,22 @@
             if (rc != LSHPACK_ERR_BAD_DATA) {
                 /* LSHPACK_ERR_TOO_LARGE, LSHPACK_ERR_MORE_BUF */
                 err = H2_E_PROTOCOL_ERROR;
+              #if 0
+                /* redundant: h2_send_goaway_e() sends RST_STREAM with
+                 * H2_E_PROTOCOL_ERROR if GOAWAY not already sent.
+                 * (If GOAWAY were sent with higher id, we would want
+                 *  to send RST_STREAM here, but that is not the case) */
                 h2_send_rst_stream(r, r->con, err);
+              #endif
             }
-            if (!h2c->sent_goaway && !hpctx.trailers)
-                h2c->h2_cid = r->x.h2.id;
-            h2_send_goaway_e(r->con, err);
             if (!hpctx.trailers) {
-                h2_retire_stream(r, r->con);
+                h2con * const h2c = (h2con *)r->con->hx;
+                if (!h2c->sent_goaway)
+                    h2c->h2_cid = r->x.h2.id;
+                h2_send_goaway_e(r->con, err);
                 return;
             }
-            else {
-                r->state = CON_STATE_ERROR;
-                r->x.h2.state = H2_STATE_CLOSED;
-            }
+            h2_send_goaway_e(r->con, err);
             break;
         }
     }
@@ -1550,6 +1667,41 @@
 }
 
 
+__attribute_cold__
+static int
+h2_discard_headers (struct lshpack_dec * const restrict decoder, const 
unsigned char **psrc, const unsigned char * const restrict endp, const 
request_st * const restrict r, h2con * const h2c)
+{
+    /* If GOAWAY was sent with an error, return quickly without decoding;
+     * choose *to not keep* HPACK decoder state in sync, since
+     * h2_send_rst_stream_state() set r->state = CON_STATE_ERROR and
+     * r->x.h2.state = H2_STATE_CLOSED for previously active streams. */
+    if (h2c->sent_goaway > 0) return 0;
+
+    /* Send error if too many discarded HEADERS frames.
+     * (similar to h2_send_refused_stream())
+     * Note: this could legitimately be triggered by a client sending trailers
+     * after lighttpd has responded to and closed a stream, so no longer 
tracked
+     * by lighttpd, but that is not expected to be a common scenario.  (Also, 
if
+     * this were permitted without limit, it could be abused to bypass 
limit.)*/
+    if (++h2c->n_discarded_headers > 32) {
+        connection * const con = r->con;
+        log_error(NULL, __FILE__, __LINE__,
+          "h2: %s too many discarded requests",
+          con->request.dst_addr_buf->ptr);
+        h2_send_goaway_e(con, H2_E_ENHANCE_YOUR_CALM);
+    }
+
+    h2_discard_headers_frame(decoder, psrc, endp, r);
+
+    /* return 1 to continue processing HTTP/2 frames
+     * Note: if returning 0 to defer processing additional frames and
+     * yield to other connections, must also joblist_append(con) unless
+     * all h2c->r slots are full and next frame is HEADERS (which could
+     * be passed in as a flag depending on the calling location) */
+    return 1;
+}
+
+
 __attribute_noinline__
 static int
 h2_recv_headers (connection * const con, uint8_t * const s, uint32_t flen)
@@ -1561,7 +1713,6 @@
      * might be made to the code in the future. */
     __coverity_tainted_data_sink__(s);
   #endif
-    request_st *r = NULL;
     h2con * const h2c = (h2con *)con->hx;
     const uint32_t id = h2_u31(s+5);
   #if 0 /*(included in (!(id & 1)) below)*/
@@ -1575,53 +1726,6 @@
         return 0;
     }
 
-    request_st * const h2r = &con->request;
-    int trailers = 0;
-
-    if (id > h2c->h2_cid) {
-        if (h2c->rused == sizeof(h2c->r)/sizeof(*h2c->r))
-            return h2_send_refused_stream(id, con);
-        /* Note: MUST process HPACK decode even if already sent GOAWAY.
-         * This is necessary since there may be active streams not in
-         * H2_STATE_HALF_CLOSED_REMOTE, e.g. H2_STATE_OPEN, still possibly
-         * receiving DATA and, more relevantly, still might receive HEADERS
-         * frame with trailers, for which the decoder state is required.
-         * XXX: future might try to reduce other processing done if sent
-         *      GOAWAY, e.g. might avoid allocating (request_st *r) */
-        r = h2_init_stream(h2r, con);
-        r->x.h2.id = id;
-        if (s[4] & H2_FLAG_END_STREAM) {
-            r->x.h2.state = H2_STATE_HALF_CLOSED_REMOTE;
-            r->state = CON_STATE_HANDLE_REQUEST;
-            r->reqbody_length = 0;
-        }
-        else {
-            r->x.h2.state = H2_STATE_OPEN;
-            r->state = CON_STATE_READ_POST;
-            r->reqbody_length = -1;
-        }
-        /* Note: timestamps here are updated only after receipt of entire 
header
-         * (HEADERS frame might have been sent in multiple packets
-         *  and CONTINUATION frames may have been sent in multiple packets)
-         * (affects high precision timestamp, if enabled)
-         * (large sets of headers are not typical, and even when they do
-         *  occur, they will typically be sent within the same second)
-         * (future: might keep high precision timestamp in h2con when first
-         *  packet of HEADERS or PUSH_PROMISE is received, and clear that
-         *  timestamp when frame + CONTINUATION(s) are complete (so that
-         *  re-read of initial frame does not overwrite the timestamp))
-         */
-        r->start_hp.tv_sec = log_epoch_secs;
-        if (r->conf.high_precision_timestamps)
-            log_clock_gettime_realtime(&r->start_hp);
-    }
-    else {
-        r = h2_recv_trailers_r(con, h2c, id, s[4]); /* (cold code path) */
-        if (NULL == r)
-            return (h2c->sent_goaway > 0) ? 0 : 1;
-        trailers = 1;
-    }
-
     const unsigned char *psrc = s + 9;
     uint32_t alen = flen;
     if (s[4] & H2_FLAG_PADDED) {
@@ -1631,23 +1735,26 @@
             /* Padding that exceeds the size remaining for the header block
              * fragment MUST be treated as a PROTOCOL_ERROR. */
             h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
-            if (!trailers)
-                h2_retire_stream(r, con);
-            else {
-                r->state = CON_STATE_ERROR;
-                r->x.h2.state = H2_STATE_CLOSED;
-            }
             return 0;
         }
         alen -= (1 + pad); /*(alen is adjusted for PRIORITY below)*/
     }
     if (s[4] & H2_FLAG_PRIORITY) {
-        /* XXX: TODO: handle PRIORITY (prio fields start at *psrc) */
-        if (alen < 5 || (/*prio = */h2_u32(psrc)) == id) {
-            h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
-            if (!trailers)
-                h2_retire_stream(r, con);
-            return 1;
+        if (alen < 5) {
+            h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
+            return 0;
+        }
+        if (((/*prio = */h2_u32(psrc)) == id) & (id > h2c->h2_cid)) {
+            /*(ignore dep if HEADERS frame is trailers (id <= h2c->h2_cid)*/
+            /* https://www.rfc-editor.org/rfc/rfc7540#section-5.3.1
+             * A stream cannot depend on itself.  An endpoint MUST treat this
+             * as a stream error (Section 5.4.2) of type PROTOCOL_ERROR.*/
+            h2_send_rst_stream_id(id, con, H2_E_PROTOCOL_ERROR);
+            /* PRIORITY is deprecated in RFC9113.  As this mistake is now more
+             * likely an attack, follow with goaway error since HEADERS frame
+             * is not HPACK decoded here to maintain HPACK decoder state. */
+            h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
+            return 0;
         }
       #if 0
         uint32_t exclusive_dependency = (psrc[0] & 0x80) ? 1 : 0;
@@ -1661,29 +1768,85 @@
         alen -= 5;
     }
 
-    h2_parse_headers_frame(r, psrc, alen, trailers);
-
-    if (__builtin_expect( (trailers), 0))
+    if (id <= h2c->h2_cid) { /* (trailers; cold code path) */
+        request_st * const r = h2_recv_trailers_r(con, h2c, id, s[4]);
+        if (NULL == r)
+            return h2_discard_headers(&h2c->decoder, &psrc, psrc+alen,
+                                      &con->request, h2c);
+        
h2_parse_headers_frame(&h2c->decoder,&psrc,psrc+alen,r,1);/*(trailers)*/
         return 1;
+    }
+
+    /* Note: MUST process HPACK decode even if already sent GOAWAY.
+     * This is necessary since there may be active streams not in
+     * H2_STATE_HALF_CLOSED_REMOTE, e.g. H2_STATE_OPEN, still possibly
+     * receiving DATA and, more relevantly, still might receive HEADERS
+     * frame with trailers, for which the decoder state may be required. */
+
+    if (h2c->sent_goaway)
+        return h2_discard_headers(&h2c->decoder, &psrc, psrc+alen,
+                                  &con->request, h2c);
 
   #if 0 /*(handled in h2_parse_frames() as a connection error)*/
-    /* not handled here:
-     * r is invalid if h2_parse_headers_frame() HPACK decode error */
     if (s[3] == H2_FTYPE_PUSH_PROMISE) {
-        /* Had to process HPACK to keep HPACK tables sync'd with peer but now
-         * discard the request if PUSH_PROMISE, since not expected, as this 
code
-         * is running as a server, not as a client.
-         * XXX: future might try to reduce other processing done if
-         * discarding, e.g. might avoid allocating (request_st *r) */
+        /* discard the request if PUSH_PROMISE, since not expected, as this 
code
+         * is running as a server, not as a client. */
+        /* note: h2_parse_headers_frame() sets h2c->h2_cid on HPACK decode 
error
+         * and would need to be changed for code to be shared by PUSH_PROMISE 
*/
         /* rant: PUSH_PROMISE could have been a flag on HEADERS frame
          *       instead of an independent frame type */
-        r->http_status = 0;
-        h2_retire_stream(r, con);
+        h2c->h2_sid = id;
+        return h2_discard_headers(&h2c->decoder, &psrc, psrc+alen,
+                                  &con->request, h2c);
     }
   #endif
 
+    /* new stream */
+
+        if (h2c->rused == sizeof(h2c->r)/sizeof(*h2c->r))
+            return h2_send_refused_stream(id, con) == -1
+              ? -1
+              : h2_discard_headers(&h2c->decoder, &psrc, psrc+alen,
+                                   &con->request, h2c);
+
+        request_st * const h2r = &con->request;
+        request_st * const r = h2_init_stream(h2r, con);
+        r->x.h2.id = id;
+        if (s[4] & H2_FLAG_END_STREAM) {
+            r->x.h2.state = H2_STATE_HALF_CLOSED_REMOTE;
+            r->state = CON_STATE_HANDLE_REQUEST;
+            r->reqbody_length = 0;
+        }
+        else {
+            r->x.h2.state = H2_STATE_OPEN;
+            r->state = CON_STATE_READ_POST;
+            r->reqbody_length = -1;
+        }
+        /* Note: timestamps here are updated only after receipt of entire 
header
+         * (HEADERS frame might have been sent in multiple packets
+         *  and CONTINUATION frames may have been sent in multiple packets)
+         * (affects high precision timestamp, if enabled)
+         * (large sets of headers are not typical, and even when they do
+         *  occur, they will typically be sent within the same second)
+         * (future: might keep high precision timestamp in h2con when first
+         *  packet of HEADERS or PUSH_PROMISE is received, and clear that
+         *  timestamp when frame + CONTINUATION(s) are complete (so that
+         *  re-read of initial frame does not overwrite the timestamp))
+         */
+        r->start_hp.tv_sec = log_epoch_secs;
+        if (r->conf.high_precision_timestamps)
+            log_clock_gettime_realtime(&r->start_hp);
+
+    h2_parse_headers_frame(&h2c->decoder, &psrc, psrc+alen, r, 0); 
/*(headers)*/
+
     if (!h2c->sent_goaway) {
         h2c->h2_cid = id;
+
+        /* counter to detect HTTP/2 rapid reset attack (CVE-2023-44487)
+         * HTTP/2 client ids are odds, so use mask 0x1f
+         * in order to reset lower counter every 16 requests */
+        if ((id & 0x1f) == 0x1) h2c->n_recv_rst_stream <<= 4;
+
         /*(lighttpd.conf config conditions not yet applied to request,
          * but do not increase window size if BUFMIN set in global config)*/
         if (r->reqbody_length /*(see h2_init_con() for session window)*/
@@ -1719,11 +1882,9 @@
         if (h2c->rused-1) /*(true if more than one active stream)*/
             h2_apply_priority_update(h2c, r, h2c->rused-1);
     }
-    else if (h2c->h2_cid < id) {
+    else {
         /* Had to process HPACK to keep HPACK tables sync'd with peer
-         * but now discard the request if id is after id sent in GOAWAY.
-         * XXX: future might try to reduce other processing done if
-         * discarding, e.g. might avoid allocating (request_st *r) */
+         * but now discard the request */
         r->http_status = 0;
         h2_retire_stream(r, con);
     }
@@ -1745,6 +1906,11 @@
      *       should accept the larger frame size until SETTINGS is ACK'd) */
     const uint32_t fsize = h2c->s_max_frame_size;
     for (off_t cqlen; (cqlen = chunkqueue_length(cq)) >= 9; ) {
+
+        /* defer parsing additional frames if large output queue pending 
write*/
+        if (__builtin_expect( (chunkqueue_length(con->write_queue) > 65536), 
0))
+            return 0;
+
         chunk *c = cq->first;
         /*assert(c->type == MEM_CHUNK);*/
         /* copy data if frame header crosses chunk boundary
@@ -3308,8 +3474,19 @@
     request_st * const h2r = &con->request;
     if (h2r->state == CON_STATE_WRITE) {
         /* write HTTP/2 frames to socket */
-        if (!chunkqueue_is_empty(con->write_queue))
+        if (!chunkqueue_is_empty(con->write_queue)) {
             connection_handle_write(h2r, con);
+            /* check if might need to resched to process more frames
+             * (could be more precise duplicating parts of h2_want_read(),
+             *  though prefer to check here when write_queue has been emptied)
+             * need to resched if still CON_STATE_WRITE, write_queue empty,
+             * full frame pending, and frame is not HEADERS or h2c->r not full,
+             * which might happen if parsing frames was deferred if write_queue
+             * grew too large generating HTTP/2 replies to various frame 
types*/
+            if (chunkqueue_is_empty(con->write_queue)
+                && !chunkqueue_is_empty(con->read_queue))
+                resched |= 2;
+        }
 
         if (chunkqueue_is_empty(con->write_queue)
             && 0 == h2c->rused && h2c->sent_goaway)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lighttpd-1.4.72/src/h2.h new/lighttpd-1.4.73/src/h2.h
--- old/lighttpd-1.4.72/src/h2.h        2023-10-07 02:10:38.000000000 +0200
+++ new/lighttpd-1.4.73/src/h2.h        2023-10-31 03:35:56.000000000 +0100
@@ -88,6 +88,9 @@
     struct lshpack_dec decoder;
     struct lshpack_enc encoder;
     unix_time64_t half_closed_ts;
+    uint8_t n_refused_stream;
+    uint8_t n_discarded_headers;
+    uint8_t n_recv_rst_stream;
 };
 typedef struct h2con h2con;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lighttpd-1.4.72/src/mod_mbedtls.c 
new/lighttpd-1.4.73/src/mod_mbedtls.c
--- old/lighttpd-1.4.72/src/mod_mbedtls.c       2023-10-07 02:10:38.000000000 
+0200
+++ new/lighttpd-1.4.73/src/mod_mbedtls.c       2023-10-31 03:35:56.000000000 
+0100
@@ -62,11 +62,15 @@
 #define MBEDTLS_ALLOW_PRIVATE_ACCESS
 #endif
 #endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include <mbedtls/psa_util.h>
+#else
 #include <mbedtls/ctr_drbg.h>
+#include <mbedtls/entropy.h>
+#endif
 #include <mbedtls/debug.h>
 #include <mbedtls/dhm.h>
 #include <mbedtls/error.h>
-#include <mbedtls/entropy.h>
 #include <mbedtls/oid.h>
 #include <mbedtls/pem.h>
 #include <mbedtls/ssl.h>
@@ -168,10 +172,12 @@
     plugin_ssl_ctx *ssl_ctxs;
     plugin_config defaults;
     server *srv;
+  #if !defined(MBEDTLS_USE_PSA_CRYPTO)
     /* NIST counter-mode deterministic random byte generator */
     mbedtls_ctr_drbg_context ctr_drbg;
     /* entropy collection and state management */
     mbedtls_entropy_context entropy;
+  #endif
   #if defined(MBEDTLS_SSL_SESSION_TICKETS)
     mbedtls_ssl_ticket_context ticket_ctx;
     const char *ssl_stek_file;
@@ -407,6 +413,14 @@
     if (ssl_is_init) return 1;
     ssl_is_init = 1;
 
+  #if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_status_t ps = psa_crypto_init();
+    if (ps != PSA_SUCCESS) {
+        log_error(srv->errh, __FILE__, __LINE__,
+          "MTLS: %s: (-0x%04x)", "psa_crypto_init()", ps);
+        return 0;
+    }
+  #else
     plugin_data * const p = plugin_data_singleton;
     mbedtls_ctr_drbg_init(&p->ctr_drbg); /* init empty NSIT random num gen */
     mbedtls_entropy_init(&p->entropy);   /* init empty entropy collection 
struct
@@ -422,6 +436,7 @@
              "Init of random number generator failed");
         return 0;
     }
+  #endif
 
     local_send_buffer = ck_malloc(LOCAL_SEND_BUFSIZE);
     return 1;
@@ -438,8 +453,12 @@
   #endif
 
     plugin_data * const p = plugin_data_singleton;
+  #if defined(MBEDTLS_USE_PSA_CRYPTO)
+    mbedtls_psa_crypto_free();
+  #else
     mbedtls_ctr_drbg_free(&p->ctr_drbg);
     mbedtls_entropy_free(&p->entropy);
+  #endif
   #if defined(MBEDTLS_SSL_SESSION_TICKETS)
     mbedtls_ssl_ticket_free(&p->ticket_ctx);
   #endif
@@ -977,11 +996,18 @@
     if (NULL == data) return rc;
 
   #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.00.0 */
+   #if defined(MBEDTLS_USE_PSA_CRYPTO)
+    rc = mbedtls_pk_parse_key(ctx, (unsigned char *)data, (size_t)dlen+1,
+                              (const unsigned char *)pwd,
+                              pwd ? strlen(pwd) : 0,
+                              mbedtls_psa_get_random, 
MBEDTLS_PSA_RANDOM_STATE);
+   #else
     plugin_data * const p = plugin_data_singleton;
     rc = mbedtls_pk_parse_key(ctx, (unsigned char *)data, (size_t)dlen+1,
                               (const unsigned char *)pwd,
                               pwd ? strlen(pwd) : 0,
                               mbedtls_ctr_drbg_random, &p->ctr_drbg);
+   #endif
   #else
     rc = mbedtls_pk_parse_key(ctx, (unsigned char *)data, (size_t)dlen+1,
                               (const unsigned char *)pwd,
@@ -1024,9 +1050,14 @@
     }
 
   #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.00.0 */
+   #if defined(MBEDTLS_USE_PSA_CRYPTO)
+    rc = mbedtls_pk_check_pair(&ssl_pemfile_x509.pk, &ssl_pemfile_pkey,
+                               
mbedtls_psa_get_random,MBEDTLS_PSA_RANDOM_STATE);
+   #else
     plugin_data * const p = plugin_data_singleton;
     rc = mbedtls_pk_check_pair(&ssl_pemfile_x509.pk, &ssl_pemfile_pkey,
                                mbedtls_ctr_drbg_random, &p->ctr_drbg);
+   #endif
   #else
     rc = mbedtls_pk_check_pair(&ssl_pemfile_x509.pk, &ssl_pemfile_pkey);
   #endif
@@ -1437,7 +1468,12 @@
     mbedtls_ssl_config_init(s->ssl_ctx);
 
     /* set the RNG in the ssl config context, using the default random func */
+  #if defined(MBEDTLS_USE_PSA_CRYPTO)
+    mbedtls_ssl_conf_rng(s->ssl_ctx,
+                         mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE);
+  #else
     mbedtls_ssl_conf_rng(s->ssl_ctx, mbedtls_ctr_drbg_random, &p->ctr_drbg);
+  #endif
 
     /* mbedtls defaults to disable client renegotiation
      * mbedtls defaults to no record compression unless mbedtls is built
@@ -1527,9 +1563,17 @@
   #if defined(MBEDTLS_SSL_SESSION_TICKETS)
     if (s->ssl_session_ticket            /*(.ticket_lifetime is private)*/
         && !*(unsigned char *)&p->ticket_ctx) { /*init once*/
+      #if defined(MBEDTLS_USE_PSA_CRYPTO)
+        rc = mbedtls_ssl_ticket_setup(&p->ticket_ctx,
+                                      mbedtls_psa_get_random,
+                                      MBEDTLS_PSA_RANDOM_STATE,
+                                      MBEDTLS_CIPHER_AES_256_GCM,
+                                      43200); /* ticket timeout: 12 hours */
+      #else
         rc = mbedtls_ssl_ticket_setup(&p->ticket_ctx, mbedtls_ctr_drbg_random,
                                       &p->ctr_drbg, MBEDTLS_CIPHER_AES_256_GCM,
                                       43200); /* ticket timeout: 12 hours */
+      #endif
         if (0 != rc) {
             elog(srv->errh,__FILE__,__LINE__,rc,"mbedtls_ssl_ticket_setup()");
             return -1;
@@ -1993,6 +2037,9 @@
         break; /* try again later */
       case MBEDTLS_ERR_SSL_WANT_WRITE:
         con->is_writable = -1;
+       #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.00.0 */
+        hctx->pending_write = wr_len; /* partial write; save attempted wr_len 
*/
+       #endif
         break; /* try again later */
       case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
       case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
@@ -2009,8 +2056,8 @@
 
   #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.00.0 */
     if (0 != hctx->ssl.out_left)  /* partial write; save attempted wr_len */
-  #endif
         hctx->pending_write = wr_len;
+  #endif
 
     return 0; /* try again later */
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lighttpd-1.4.72/src/mod_openssl.c 
new/lighttpd-1.4.73/src/mod_openssl.c
--- old/lighttpd-1.4.72/src/mod_openssl.c       2023-10-07 02:10:38.000000000 
+0200
+++ new/lighttpd-1.4.73/src/mod_openssl.c       2023-10-31 03:35:56.000000000 
+0100
@@ -82,6 +82,7 @@
 #include <openssl/ocsp.h>
 #endif
 #ifdef BORINGSSL_API_VERSION
+#include <openssl/hmac.h>
 /* BoringSSL purports to have some OCSP support */
 #undef OPENSSL_NO_OCSP
 #endif
@@ -2191,7 +2192,8 @@
 
 
 #if defined(BORINGSSL_API_VERSION) \
- || defined(LIBRESSL_VERSION_NUMBER)
+ || defined(LIBRESSL_VERSION_NUMBER) \
+ || OPENSSL_VERSION_NUMBER < 0x10100000L
 static int
 mod_openssl_ssl_conf_curves(server *srv, plugin_config_socket *s, const buffer 
*ssl_ec_curve)
 {
@@ -2254,6 +2256,7 @@
     return 1;
 }
 #endif /* BORINGSSL_API_VERSION || LIBRESSL_VERSION_NUMBER */
+       /* || OPENSSL_VERSION_NUMBER < 0x10100000L */
 
 
 static int
@@ -2365,6 +2368,11 @@
         if (!mod_openssl_ssl_conf_dhparameters(srv, s, NULL))
             return -1;
 
+      #if OPENSSL_VERSION_NUMBER < 0x10100000L
+        if (!mod_openssl_ssl_conf_curves(srv, s, NULL))
+            return -1;
+      #endif
+
       #ifdef TLSEXT_TYPE_session_ticket
        #if OPENSSL_VERSION_NUMBER < 0x30000000L
         SSL_CTX_set_tlsext_ticket_key_cb(s->ssl_ctx, ssl_tlsext_ticket_key_cb);
@@ -2996,11 +3004,12 @@
             mod_openssl_merge_config(&p->defaults, cpv);
     }
 
-  #if OPENSSL_VERSION_NUMBER < 0x10101000L \
+  #if OPENSSL_VERSION_NUMBER < 0x30000000L \
+   && !defined(BORINGSSL_API_VERSION) \
    && !defined(LIBRESSL_VERSION_NUMBER)
     log_error(srv->errh, __FILE__, __LINE__, "SSL:"
       "openssl library version is outdated and has reached end-of-life.  "
-      "As of 1 Jan 2020, only openssl 1.1.1 and later continue to receive "
+      "As of 11 Sep 2023, only openssl 3.0.0 and later continue to receive "
       "security patches from openssl.org");
   #endif
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lighttpd-1.4.72/src/mod_wstunnel.c 
new/lighttpd-1.4.73/src/mod_wstunnel.c
--- old/lighttpd-1.4.72/src/mod_wstunnel.c      2023-10-07 02:10:38.000000000 
+0200
+++ new/lighttpd-1.4.73/src/mod_wstunnel.c      2023-10-31 03:35:56.000000000 
+0100
@@ -822,7 +822,7 @@
     buffer_append_base64_encode(value, sha_digest, SHA_DIGEST_LENGTH, 
BASE64_STANDARD);
   }
 
-    if (hctx->frame.type == MOD_WEBSOCKET_FRAME_TYPE_BIN)
+    if (1 == hctx->subproto)
         http_header_response_set(r, HTTP_HEADER_OTHER,
                                  CONST_STR_LEN("Sec-WebSocket-Protocol"),
                                  CONST_STR_LEN("binary"));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lighttpd-1.4.72/src/plugin.c 
new/lighttpd-1.4.73/src/plugin.c
--- old/lighttpd-1.4.72/src/plugin.c    2023-10-07 02:10:38.000000000 +0200
+++ new/lighttpd-1.4.73/src/plugin.c    2023-10-31 03:35:56.000000000 +0100
@@ -131,13 +131,15 @@
                        }
                }
                if (!load_functions[j].name) {
-                       log_error(srv->errh, __FILE__, __LINE__, "%s plugin not 
found", module);
                        if (srv->srvconf.compat_module_load) {
                                if (buffer_eq_slen(&ds->value, 
CONST_STR_LEN("mod_deflate")))
                                        continue;
                        }
-                       if (buffer_eq_slen(&ds->value, CONST_STR_LEN("mod_h2")))
+                       if (buffer_eq_slen(&ds->value, 
CONST_STR_LEN("mod_h2"))) {
+                               srv->srvconf.h2proto = 0;
                                continue;
+                       }
+                       log_error(srv->errh, __FILE__, __LINE__, "%s plugin not 
found", module);
                        return -1;
                }
        }
@@ -180,14 +182,16 @@
          #ifdef _WIN32
                buffer_append_string_len(tb, CONST_STR_LEN(".dll"));
                if (NULL == (lib = LoadLibrary(tb->ptr))) {
-                       log_perror(srv->errh, __FILE__, __LINE__,
-                         "LoadLibrary() %s", tb->ptr);
                        if (srv->srvconf.compat_module_load) {
                                if (buffer_eq_slen(module, 
CONST_STR_LEN("mod_deflate")))
                                        continue;
                        }
-                       if (buffer_eq_slen(module, CONST_STR_LEN("mod_h2")))
+                       if (buffer_eq_slen(module, CONST_STR_LEN("mod_h2"))) {
+                               srv->srvconf.h2proto = 0;
                                continue;
+                       }
+                       log_perror(srv->errh, __FILE__, __LINE__,
+                         "LoadLibrary() %s", tb->ptr);
                        return -1;
                }
                buffer_copy_buffer(tb, module);
@@ -206,14 +210,16 @@
                buffer_append_string_len(tb, CONST_STR_LEN(".so"));
           #endif
                if (NULL == (lib = dlopen(tb->ptr, RTLD_NOW|RTLD_GLOBAL))) {
-                       log_error(srv->errh, __FILE__, __LINE__,
-                         "dlopen() failed for: %s %s", tb->ptr, dlerror());
                        if (srv->srvconf.compat_module_load) {
                                if (buffer_eq_slen(module, 
CONST_STR_LEN("mod_deflate")))
                                        continue;
                        }
-                       if (buffer_eq_slen(module, CONST_STR_LEN("mod_h2")))
+                       if (buffer_eq_slen(module, CONST_STR_LEN("mod_h2"))) {
+                               srv->srvconf.h2proto = 0;
                                continue;
+                       }
+                       log_error(srv->errh, __FILE__, __LINE__,
+                         "dlopen() failed for: %s %s", tb->ptr, dlerror());
                        return -1;
                }
                buffer_clear(tb);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lighttpd-1.4.72/src/rand.c 
new/lighttpd-1.4.73/src/rand.c
--- old/lighttpd-1.4.72/src/rand.c      2023-10-07 02:10:38.000000000 +0200
+++ new/lighttpd-1.4.73/src/rand.c      2023-10-31 03:35:56.000000000 +0100
@@ -41,9 +41,13 @@
 #undef USE_OPENSSL_CRYPTO
 #undef USE_GNUTLS_CRYPTO
 #undef USE_NSS_CRYPTO
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include <mbedtls/psa_util.h>
+#else
 #include <mbedtls/ctr_drbg.h>
 #include <mbedtls/entropy.h>
 #endif
+#endif
 #ifdef USE_WOLFSSL_CRYPTO
 #undef USE_OPENSSL_CRYPTO
 #undef USE_GNUTLS_CRYPTO
@@ -219,6 +223,7 @@
 static int li_rand_inited;
 static unsigned short xsubi[3];
 #ifdef USE_MBEDTLS_CRYPTO
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
 #ifdef MBEDTLS_ENTROPY_C
 static mbedtls_entropy_context entropy;
 #ifdef MBEDTLS_CTR_DRBG_C
@@ -226,6 +231,7 @@
 #endif
 #endif
 #endif
+#endif
 #ifdef USE_WOLFSSL_CRYPTO
 static WC_RNG wolf_globalRNG;
 #endif
@@ -334,6 +340,11 @@
     RAND_seed(xsubi, (int)sizeof(xsubi));
   #endif
   #ifdef USE_MBEDTLS_CRYPTO
+  #if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_status_t ps = psa_crypto_init();
+    if (ps != PSA_SUCCESS)
+        ck_bt_abort(__FILE__, __LINE__, "psa_crypto_init() failed");
+  #else
   #ifdef MBEDTLS_ENTROPY_C
     mbedtls_entropy_init(&entropy);
   #ifdef MBEDTLS_CTR_DRBG_C
@@ -346,6 +357,7 @@
   #endif
   #endif
   #endif
+  #endif
   #ifdef USE_NSS_CRYPTO
     if (!NSS_IsInitialized() && NSS_NoDB_Init(NULL) < 0)
         ck_bt_abort(__FILE__, __LINE__, "aborted");
@@ -382,13 +394,28 @@
   #endif
   #ifdef USE_MBEDTLS_CRYPTO
     if (li_rand_inited) {
+      #if defined(MBEDTLS_USE_PSA_CRYPTO)
+        mbedtls_psa_crypto_free();
+      #else
       #ifdef MBEDTLS_ENTROPY_C
       #ifdef MBEDTLS_CTR_DRBG_C
         mbedtls_ctr_drbg_free(&ctr_drbg);
       #endif
         mbedtls_entropy_free(&entropy);
       #endif
+      #endif
+    }
+   #if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_CRYPTO_DRIVER_TEST)
+    else {
+        /*(kludge to call psa_crypto_init() for sys-crypto-md.h from 
server.c)*/
+        /*(However, we prefer to defer RNG initialization, and the builtin hash
+         * functions do not require psa_crypto_init(), so skip unless hash func
+         * might use an accelerated crypto driver)*/
+        psa_status_t ps = psa_crypto_init();
+        if (ps != PSA_SUCCESS)
+            ck_bt_abort(__FILE__, __LINE__, "psa_crypto_init() failed");
     }
+   #endif
   #endif
     if (li_rand_inited) li_rand_init();
 }
@@ -420,12 +447,19 @@
     if (i) return i; /*(cond to avoid compiler warning for code after return)*/
   #endif
   #ifdef USE_MBEDTLS_CRYPTO
+  #if defined(MBEDTLS_USE_PSA_CRYPTO)
+    int i;
+    if (0 == mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE,
+                                    (unsigned char *)&i, sizeof(i)))
+        return i;
+  #else
   #ifdef MBEDTLS_CTR_DRBG_C
     int i;
     if (0 == mbedtls_ctr_drbg_random(&ctr_drbg, (unsigned char *)&i, 
sizeof(i)))
         return i;
   #endif
   #endif
+  #endif
   #ifdef USE_NSS_CRYPTO
     int i;
     if (SECSuccess == PK11_GenerateRandom((unsigned char *)&i, sizeof(i)))
@@ -466,10 +500,14 @@
     if (SECSuccess == PK11_GenerateRandom(buf, num)) return;
   #endif
   #ifdef USE_MBEDTLS_CRYPTO
+  #if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (0 == psa_generate_random(buf, (size_t)num)) return;
+  #else
   #ifdef MBEDTLS_CTR_DRBG_C
     if (0 == mbedtls_ctr_drbg_random(&ctr_drbg, buf, (size_t)num)) return;
   #endif
   #endif
+  #endif
   #ifdef USE_WOLFSSL_CRYPTO
     /* RAND_pseudo_bytes() in WolfSSL is equivalent to RAND_bytes() */
     if (0 == wc_RNG_GenerateBlock(&wolf_globalRNG, (byte *)buf, (word32)num))
@@ -479,6 +517,7 @@
         buf[i] = li_rand_pseudo() & 0xFF;
 }
 
+#if 0 /*(unused)*/
 int li_rand_bytes (unsigned char *buf, int num)
 {
   #ifdef USE_GNUTLS_CRYPTO /* should use GNUTLS_RND_KEY for long-term keys */
@@ -516,6 +555,10 @@
   #endif
   #ifdef USE_MBEDTLS_CRYPTO
   #ifdef MBEDTLS_ENTROPY_C
+  #if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (0 == psa_generate_random(buf, (size_t)num))
+        return 1;
+  #else
     /*(each call <= MBEDTLS_ENTROPY_BLOCK_SIZE; could implement loop here)*/
     if (num <= MBEDTLS_ENTROPY_BLOCK_SIZE
         && 0 == mbedtls_entropy_func(&entropy, buf, (size_t)num)) {
@@ -523,6 +566,7 @@
     }
   #endif
   #endif
+  #endif
     if (1 == li_rand_device_bytes(buf, num)) {
         return 1;
     }
@@ -533,6 +577,7 @@
         return 0;
     }
 }
+#endif
 
 void li_rand_cleanup (void)
 {
@@ -549,6 +594,9 @@
   #endif
   #endif
   #ifdef USE_MBEDTLS_CRYPTO
+  #if defined(MBEDTLS_USE_PSA_CRYPTO)
+    mbedtls_psa_crypto_free();
+  #else
   #ifdef MBEDTLS_ENTROPY_C
   #ifdef MBEDTLS_CTR_DRBG_C
     mbedtls_ctr_drbg_free(&ctr_drbg);
@@ -556,5 +604,7 @@
     mbedtls_entropy_free(&entropy);
   #endif
   #endif
+    li_rand_inited = 0;
+  #endif /* USE_MBEDTLS_CRYPTO */
     ck_memzero(xsubi, sizeof(xsubi));
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lighttpd-1.4.72/src/sys-crypto-md.h 
new/lighttpd-1.4.73/src/sys-crypto-md.h
--- old/lighttpd-1.4.72/src/sys-crypto-md.h     2023-10-07 02:10:38.000000000 
+0200
+++ new/lighttpd-1.4.73/src/sys-crypto-md.h     2023-10-31 03:35:56.000000000 
+0100
@@ -153,6 +153,102 @@
 #include <mbedtls/version.h>
 /*#include <mbedtls/compat-2.x.h>*//*(func renames ifdef'd below)*/
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "psa/crypto.h"
+/* Note: psa_crypto_init() MUST be called once before use
+ * (see lighttpd src/rand.c for overload where this is done in lighttpd) */
+#include <string.h>     /* memset() */
+
+#ifdef PSA_WANT_ALG_MD5
+#define USE_LIB_CRYPTO_MD5
+typedef psa_hash_operation_t MD5_CTX;
+static inline int
+MD5_Init(MD5_CTX *ctx)
+{
+    memset(ctx, 0, sizeof(MD5_CTX));
+    return (PSA_SUCCESS == psa_hash_setup(ctx, PSA_ALG_MD5));
+}
+static inline int
+MD5_Final(unsigned char *digest, MD5_CTX *ctx)
+{
+    size_t n;        /* PSA_HASH_LENGTH(PSA_ALG_MD5) == 16 */
+    return (PSA_SUCCESS == psa_hash_finish(ctx, digest, 16, &n));
+}
+static inline int
+MD5_Update(MD5_CTX *ctx, const void *data, size_t length)
+{
+    return (PSA_SUCCESS == psa_hash_update(ctx, data, length));
+}
+#endif
+
+#ifdef PSA_WANT_ALG_SHA_1
+#define USE_LIB_CRYPTO_SHA1
+typedef psa_hash_operation_t SHA_CTX;
+static inline int
+SHA1_Init(SHA_CTX *ctx)
+{
+    memset(ctx, 0, sizeof(SHA_CTX));
+    return (PSA_SUCCESS == psa_hash_setup(ctx, PSA_ALG_SHA_1));
+}
+static inline int
+SHA1_Final(unsigned char *digest, SHA_CTX *ctx)
+{
+    size_t n;      /* PSA_HASH_LENGTH(PSA_ALG_SHA_1) == 20 */
+    return (PSA_SUCCESS == psa_hash_finish(ctx, digest, 20, &n));
+}
+static inline int
+SHA1_Update(SHA_CTX *ctx, const void *data, size_t length)
+{
+    return (PSA_SUCCESS == psa_hash_update(ctx, data, length));
+}
+#endif
+
+#ifdef PSA_WANT_ALG_SHA_256
+#define USE_LIB_CRYPTO_SHA256
+typedef psa_hash_operation_t SHA256_CTX;
+static inline int
+SHA256_Init(SHA256_CTX *ctx)
+{
+    memset(ctx, 0, sizeof(SHA256_CTX));
+    return (PSA_SUCCESS == psa_hash_setup(ctx, PSA_ALG_SHA_256));
+}
+static inline int
+SHA256_Final(unsigned char *digest, SHA256_CTX *ctx)
+{
+    size_t n;    /* PSA_HASH_LENGTH(PSA_ALG_SHA_256) == 32 */
+    return (PSA_SUCCESS == psa_hash_finish(ctx, digest, 32, &n));
+}
+static inline int
+SHA256_Update(SHA256_CTX *ctx, const void *data, size_t length)
+{
+    return (PSA_SUCCESS == psa_hash_update(ctx, data, length));
+}
+#endif
+
+#ifdef PSA_WANT_ALG_SHA_512
+#define USE_LIB_CRYPTO_SHA512
+typedef psa_hash_operation_t SHA512_CTX;
+static inline int
+SHA512_Init(SHA512_CTX *ctx)
+{
+    memset(ctx, 0, sizeof(SHA512_CTX));
+    return (PSA_SUCCESS == psa_hash_setup(ctx, PSA_ALG_SHA_512));
+}
+static inline int
+SHA512_Final(unsigned char *digest, SHA512_CTX *ctx)
+{
+    size_t n;    /* PSA_HASH_LENGTH(PSA_ALG_SHA_512) == 64 */
+    return (PSA_SUCCESS == psa_hash_finish(ctx, digest, 64, &n));
+}
+static inline int
+SHA512_Update(SHA512_CTX *ctx, const void *data, size_t length)
+{
+    return (PSA_SUCCESS == psa_hash_update(ctx, data, length));
+}
+#endif
+
+#else /* !MBEDTLS_USE_PSA_CRYPTO */
+
 #ifdef MBEDTLS_MD4_C
 #define USE_LIB_CRYPTO_MD4
 #include <mbedtls/md4.h>
@@ -321,6 +417,8 @@
 }
 #endif
 
+#endif /* !MBEDTLS_USE_PSA_CRYPTO */
+
 #elif defined(USE_WOLFSSL_CRYPTO)
 
 /* WolfSSL compatibility API for OpenSSL unnecessarily bounces through an extra
@@ -912,8 +1010,34 @@
 /* message digest wrappers operating on single ptr, and on const_iovec */
 
 
+#if defined(USE_MBEDTLS_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+
+#define li_md_once(algo, alg)                                             \
+  static inline int                                                       \
+  algo##_once (unsigned char * const digest,                              \
+               const void * const data, const size_t n)                   \
+  {                                                                       \
+      size_t x;                                                           \
+      return PSA_SUCCESS                                                  \
+          == psa_hash_compute(alg,data,n,digest,PSA_HASH_LENGTH(alg),&x); \
+  }
+li_md_once(MD5,        PSA_ALG_MD5)
+li_md_once(SHA1,       PSA_ALG_SHA_1)
+li_md_once(SHA256,     PSA_ALG_SHA_256)
+li_md_once(SHA256_512, PSA_ALG_SHA_512_256)
+li_md_once(SHA512,     PSA_ALG_SHA_512)
+
+#endif
+#endif
+
+
 typedef void(*li_md_once_fn)(unsigned char *digest, const void *data, size_t 
n);
 
+#ifdef li_md_once
+#undef li_md_once
+#define li_md_once(algo)
+#else
 #define li_md_once(algo)                                            \
   static inline void                                                \
   algo##_once (unsigned char * const digest,                        \
@@ -924,6 +1048,7 @@
       algo##_Update(&ctx, data, n);                                 \
       algo##_Final(digest, &ctx);                                   \
   }
+#endif
 
 #ifndef LI_CONST_IOVEC
 #define LI_CONST_IOVEC

Reply via email to