libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

fuzz_tls.c (78790B)


      1 /*
      2   This file is part of libmicrohttpd
      3   Copyright (C) 2026 Christian Grothoff
      4 
      5   This library is free software; you can redistribute it and/or
      6   modify it under the terms of the GNU Lesser General Public
      7   License as published by the Free Software Foundation; either
      8   version 2.1 of the License, or (at your option) any later version.
      9 
     10   This library is distributed in the hope that it will be useful,
     11   but WITHOUT ANY WARRANTY; without even the implied warranty of
     12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13   Lesser General Public License for more details.
     14 
     15   You should have received a copy of the GNU Lesser General Public
     16   License along with this library.
     17   If not, see <http://www.gnu.org/licenses/>.
     18 */
     19 
     20 /**
     21  * @file fuzz/fuzz_tls.c
     22  * @brief In-process fuzzer for MHD's HTTPS/TLS integration layer.
     23  * @author Christian Grothoff
     24  *
     25  * The target is **MHD's own TLS plumbing**, not GnuTLS.  GnuTLS has its
     26  * own OSS-Fuzz project and its record parser is not our bug surface, so
     27  * only a small part of the input budget is spent throwing raw bytes at a
     28  * TLS socket.  What this harness really exercises is
     29  *
     30  *  - the @c MHD_USE_TLS daemon option surface: #MHD_OPTION_HTTPS_MEM_KEY,
     31  *    #MHD_OPTION_HTTPS_MEM_CERT, #MHD_OPTION_HTTPS_MEM_TRUST,
     32  *    #MHD_OPTION_HTTPS_MEM_DHPARAMS, #MHD_OPTION_HTTPS_PRIORITIES,
     33  *    #MHD_OPTION_HTTPS_PRIORITIES_APPEND, #MHD_OPTION_HTTPS_CRED_TYPE,
     34  *    #MHD_OPTION_HTTPS_KEY_PASSWORD, #MHD_OPTION_TLS_NO_ALPN and the SNI
     35  *    callback #MHD_OPTION_HTTPS_CERT_CALLBACK -- with malformed PEM
     36  *    blobs, mismatched key/certificate pairs, bogus priority strings,
     37  *    credential types MHD does not support, and an SNI callback that
     38  *    fails or answers with garbage;
     39  *  - the handshake state machine of connection_https.c
     40  *    (#MHD_TLS_CONN_INIT -> HANDSHAKING -> CONNECTED / TLS_FAILED) and
     41  *    what MHD does when the handshake fails, is abandoned half way, or
     42  *    the peer disappears while MHD is still in it;
     43  *  - the transition from the handshake to the ordinary HTTP parser, and
     44  *    the TLS receive/send adapters and @c gnutls_bye() shutdown path that
     45  *    the connection uses afterwards.
     46  *
     47  * To reach that last group the harness contains a real, in-process GnuTLS
     48  * *client*.  Both ends of an @c AF_UNIX @c socketpair() are non-blocking
     49  * and everything runs in one thread: the client's @c gnutls_handshake()
     50  * is called until it answers @c GNUTLS_E_AGAIN, then the daemon is pumped
     51  * with MHD_run(), and so on.  No threads, no ports, no TCP stack, and --
     52  * because the client's handshake timeout is set to
     53  * @c GNUTLS_INDEFINITE_TIMEOUT -- no wall clock either.
     54  *
     55  * Input format (see README):
     56  *
     57  *   byte 0   certificate/key pair selector (valid, mismatched, truncated,
     58  *            garbage, absent, or built from the fuzzer's own bytes)
     59  *   byte 1   which TLS daemon options to pass at all (bitmask)
     60  *              0x01 MHD_OPTION_HTTPS_MEM_TRUST
     61  *              0x02 MHD_OPTION_HTTPS_MEM_DHPARAMS
     62  *              0x04 MHD_OPTION_HTTPS_CERT_CALLBACK (the SNI callback)
     63  *              0x08 MHD_OPTION_HTTPS_PRIORITIES[_APPEND]
     64  *              0x10 MHD_OPTION_HTTPS_CRED_TYPE
     65  *              0x20 MHD_OPTION_TLS_NO_ALPN
     66  *              0x40 MHD_OPTION_HTTPS_KEY_PASSWORD
     67  *              0x80 use _PRIORITIES_APPEND instead of _PRIORITIES
     68  *   byte 2   priority string selector
     69  *   byte 3   bits 0-2 credential type (certificate, PSK, anon, SRP, IA,
     70  *                     and two values GnuTLS does not define)
     71  *            bits 3-5 SNI callback behaviour
     72  *            bit  6   trust blob: CA certificate or garbage
     73  *            bit  7   DH parameters: valid or garbage
     74  *   byte 4   bits 0-1 client mode
     75  *                     0 raw bytes, 1 real TLS client,
     76  *                     2 real client, handshake abandoned half way,
     77  *                     3 raw bytes shaped like TLS records
     78  *            bit  2   client sends a server name (SNI)
     79  *            bit  3   client presents a client certificate
     80  *            bits 4-5 client priority string selector
     81  *            bit  6   gnutls_bye() before closing
     82  *            bit  7   shutdown(SHUT_WR) before closing
     83  *   byte 5   low nibble  MHD_OPTION_CONNECTION_MEMORY_LIMIT selector
     84  *            high nibble event loop: MHD_run() vs MHD_get_fdset*() +
     85  *                        MHD_run_from_select*()
     86  *   byte 6   handler behaviour and introspection
     87  *              bits 0-1 response constructor
     88  *              bit  2   MHD_get_connection_info() for the TLS members
     89  *              bit  3   MHD_get_daemon_info()
     90  *              bit  4   MHD_set_connection_option()
     91  *              bit  5   answer 403 instead of 200
     92  *              bit  6   add a response header
     93  *              bit  7   MHD_quiesce_daemon() before stopping
     94  *   byte 7   bits 0-2 handshake round budget (client mode 2)
     95  *            bit  3   pass the HTTPS options to a daemon started *without*
     96  *                     MHD_USE_TLS
     97  *            bit  4   MHD_ALLOW_UPGRADE
     98  *            bits 5-7 extra pump rounds
     99  *   byte 8   how many bytes of the segment stream are spliced into the
    100  *            fuzzer-built PEM blobs (see cred_tbl entries 12 and 13)
    101  *   byte 9   bits 0-2 the server name the client presents, as an index
    102  *            into a small built-in table; an op 1 segment overrides it
    103  *   byte 10. a sequence of segments, each introduced by a little-endian
    104  *            16 bit header  (op << 14) | length
    105  *              op 0  send the payload
    106  *              op 1  the payload is the server name the *next* client
    107  *                    connection presents; nothing is sent
    108  *              op 2  send the payload and pump the daemon extra rounds
    109  *              op 3  close the connection, open a fresh one (which means
    110  *                    a fresh handshake), then send
    111  *
    112  * All ten configuration bytes are mandatory; a shorter input is
    113  * rejected.
    114  *
    115  * The segment encoding is byte-for-byte the one fuzz_request uses, and
    116  * `corpus/` is shared by every harness in this directory (see README
    117  * section 3), so the seeds below deliberately contain **no op 1
    118  * segment**: fuzz_request reads op 1 as the declared decoded request
    119  * body of its own body oracle, and would report a spurious finding when
    120  * it replays a fuzz_tls seed.  That is what byte 9 is for.  Inputs the
    121  * generator or a mutator produces may use op 1 freely -- they never end
    122  * up in `corpus/`.
    123  *
    124  * The certificates and keys are the ones from
    125  * `src/testcurl/https/tls_test_keys.h` (the CA certificate, the
    126  * CA-signed server certificate with its key, and the self-signed server
    127  * certificate with its key), reproduced verbatim so that this harness
    128  * stays a single translation unit.  The DH parameters are RFC 3526
    129  * group 14, as emitted by `certtool --get-dh-params --sec-param medium`.
    130  *
    131  * The whole harness is guarded by #HTTPS_SUPPORT: `contrib/oss-fuzz/
    132  * build.sh` configures `--disable-https` (that is what makes the
    133  * MemorySanitizer build possible), and in such a build this file must
    134  * still compile to a valid, trivially passing fuzz target.
    135  */
    136 
    137 #define FUZZ_HARNESS_NAME "fuzz_tls"
    138 #include "fuzz_common.h"
    139 
    140 /* Pulls in MHD_config.h, which is where HTTPS_SUPPORT is defined.  It
    141    must come before <microhttpd.h>: it also settles FD_SETSIZE. */
    142 #include "mhd_options.h"
    143 
    144 #ifdef HTTPS_SUPPORT
    145 
    146 #include <microhttpd.h>
    147 #include <gnutls/gnutls.h>
    148 #include <gnutls/abstract.h>
    149 #include <sys/socket.h>
    150 #include <netinet/in.h>
    151 #include <sys/select.h>
    152 #include <arpa/inet.h>
    153 
    154 /**
    155  * LeakSanitizer suppressions, compiled into the harness so that they
    156  * cannot be forgotten on the command line.
    157  *
    158  * There is exactly one entry and it is *not* about MHD.  GnuTLS 3.8.9
    159  * leaks the partially parsed certificate when a PEM certificate blob
    160  * ends before its "-----END CERTIFICATE-----" line:
    161  *
    162  *     gnutls_certificate_allocate_credentials (&cred);
    163  *     gnutls_certificate_set_x509_key_mem (cred, &truncated_cert,
    164  *                                          &good_key,
    165  *                                          GNUTLS_X509_FMT_PEM);
    166  *        -> GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR (-207)
    167  *     gnutls_certificate_free_credentials (cred);
    168  *
    169  * leaks 9672 bytes in 57 allocations with no libmicrohttpd in the
    170  * picture at all (reproduced with a 40 line program).  MHD passes the
    171  * blob straight through and frees the credentials on every path, so
    172  * there is nothing for MHD to fix and nothing for this harness to find;
    173  * GnuTLS is fuzzed separately by its own OSS-Fuzz project.
    174  *
    175  * The suppression matches only allocations made *inside* GnuTLS's
    176  * certificate parser.  A credential object leaked by MHD itself is a
    177  * direct leak from gnutls_certificate_allocate_credentials() and is
    178  * still reported, as is every other MHD allocation.
    179  */
    180 const char *
    181 __lsan_default_suppressions (void);
    182 
    183 const char *
    184 __lsan_default_suppressions (void)
    185 {
    186   return "leak:gnutls_x509_crt_init\n";
    187 }
    188 
    189 
    190 #define MAX_SEGMENTS 48
    191 #define MAX_CONNECTIONS 3
    192 #define RESP_BUF_SIZE 16384
    193 #define GEN_BUF_SIZE 4096
    194 #define MAX_SNI_LEN 255
    195 #define FUZZ_PEM_BODY_MAX 1024
    196 
    197 /** Number of client priority strings offered to the input. */
    198 #define CLIENT_PRIO_COUNT 4
    199 
    200 /**
    201  * Upper bound on the number of client/server round trips spent on one
    202  * handshake.  A TLS 1.3 handshake over a socketpair needs a handful; the
    203  * cap only has to guarantee termination.
    204  */
    205 #define HANDSHAKE_ROUNDS 64
    206 
    207 
    208 /* ------------------------------------------------------------------ */
    209 /* Test credentials                                                    */
    210 /* ------------------------------------------------------------------ */
    211 
    212 /*
    213  * Taken verbatim from src/testcurl/https/tls_test_keys.h (the CA
    214  * certificate, the CA-signed server certificate and its key, and the
    215  * self-signed server certificate and its key), so that this harness
    216  * stays a single translation unit.  dh_params_pem is RFC 3526 group 14,
    217  * as emitted by "certtool --get-dh-params --sec-param medium".
    218  */
    219 
    220 static const char ca_cert_pem[] =
    221   "-----BEGIN CERTIFICATE-----\n"
    222   "MIIGITCCBAmgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCUlUx\n"
    223   "DzANBgNVBAgMBk1vc2NvdzEPMA0GA1UEBwwGTW9zY293MRswGQYDVQQKDBJ0ZXN0\n"
    224   "LWxpYm1pY3JvaHR0cGQxITAfBgkqhkiG9w0BCQEWEm5vYm9keUBleGFtcGxlLm9y\n"
    225   "ZzEQMA4GA1UEAwwHdGVzdC1DQTAgFw0yMTA0MDcxNzM2MThaGA8yMTIxMDMxNDE3\n"
    226   "MzYxOFowgYExCzAJBgNVBAYTAlJVMQ8wDQYDVQQIDAZNb3Njb3cxDzANBgNVBAcM\n"
    227   "Bk1vc2NvdzEbMBkGA1UECgwSdGVzdC1saWJtaWNyb2h0dHBkMSEwHwYJKoZIhvcN\n"
    228   "AQkBFhJub2JvZHlAZXhhbXBsZS5vcmcxEDAOBgNVBAMMB3Rlc3QtQ0EwggIiMA0G\n"
    229   "CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDdaWupA4qZjCBNkJoJOm5xnCaizl36\n"
    230   "ZLUwp4xBL/YfXPWE3LkmAREiVI/YnAb8l6G7CJnz8dTsOJWkNXG6T1KVP5/2RvBI\n"
    231   "IaaaufRIAl7hEnj1j9E2hQlV2fxF2ZNhz+nqi0LqKV4LJSpclkXADf2FA9HsVRP/\n"
    232   "B7zYh+DP0fSU8V6bsu8XCeRGshroAPrc8rH8lFEEXpNLNIqQr8yKx6SmdB6hfja6\n"
    233   "6SQ0++qBhl0aJtn4LHWZohgjBmkIaGFPYIJLgxQ/xyp2Grz2q7lGKJ+zBkBF8iOP\n"
    234   "t3x+F1hSCBnr/DGYWmjEm5tYm+7pyuriPddXdCc8+qa2LxMZo3EXxLo5YISpPCyw\n"
    235   "Z7V3YAOZTr3m1C24LiYvPehCq1CTIkhhmqtlVJXU7ISD48cx9y+5Pi34wtbTI/gN\n"
    236   "x4voyTLAfyavKMmIpxxIRsWldiF2n06HdvCRVdihDQUad10ygTmWf1J/s2ZETAtH\n"
    237   "QaSd7MD389t6nQFtTIXigsNKnnDPlrtxt7rOLvLQeR0K04Gzrf/scheOanRAfOXH\n"
    238   "KNBFU7YkDFG8rqizlC65rx9qeXFYXQcHZTuqxK7tgZnSgJat3E70VbTSCsEEG7eR\n"
    239   "bNX/fChUKAIIpWaiW6HDlKLl6m2y+BzM91umBsKOqTvntMVFBSF9pVYlXK854aIR\n"
    240   "q8A2Xujd012seQIDAQABo4GfMIGcMAsGA1UdDwQEAwICpDASBgNVHRMBAf8ECDAG\n"
    241   "AQH/AgEBMB0GA1UdDgQWBBRYdUPApWoxw4U13Rqsjf9AHdbpLDATBgNVHSUEDDAK\n"
    242   "BggrBgEFBQcDATAkBglghkgBhvhCAQ0EFxYVVGVzdCBsaWJtaWNyb2h0dHBkIENB\n"
    243   "MB8GA1UdIwQYMBaAFFh1Q8ClajHDhTXdGqyN/0Ad1uksMA0GCSqGSIb3DQEBCwUA\n"
    244   "A4ICAQBvrrcTKVeI1EYnXo4BQD4oCvf9z1fYQmL21EbHwgjg1nmaPkvStgWAc5p1\n"
    245   "kKwySrpEMKXfu68X76RccXZyWWIamEjz2OCWYZgjX6d6FpjhLphL8WxXDy5C9eay\n"
    246   "ixN7+URz2XQoi22wqR+tCPDhrIzcMPyMkx/6gRgcYeDnaFrkdSeSsKsID4plfcIj\n"
    247   "ISWJDvv+IAgrtsG1NVHnGwpAv0od3A8/4/fR6PPyewaU3aydvjZ7Au8O9DGDjlU9\n"
    248   "9HdlOkkY6GVJ1pfGZib7cV7lhy0D2kj1g9xZh97YjpoUfppPl9r+6A8gDm0hXlAD\n"
    249   "TlzNYlwTb681ZEoSd9PiLEY8HETssHlays2dYXdcNwAEp69iIHz8q1Q98Be9LScl\n"
    250   "WEzgaOT9U7lpIw/MWbELoMsC+Ecs1cVWBIuiIq8aSG2kRr1x3S8yVXbAohAXif2s\n"
    251   "E6puieM/VJ25iaNhkbLmDkk58QVVmn9NZNv6ETxuSQMp9e0EwbVlj68vzClQ91Y/\n"
    252   "nmAiGcLFUEwB9G0szv9+vR+oDW4IkvdFZSUbcICd2cnynnwAD395onqS4hEZO1xM\n"
    253   "Gy5ZldbTMTjgn7fChNopz15ChPBnwFIjhm+S0CyiLRQAowfknRVq2IBkj7/5kOWg\n"
    254   "4mcxcq76HoQWK/8X/8RFL1eFVAvY7TNHYJ0RS51DMuwCNQictA==\n"
    255   "-----END CERTIFICATE-----\n";
    256 
    257 
    258 static const char srv_signed_key_pem[] =
    259   "-----BEGIN PRIVATE KEY-----\n"
    260   "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCff7amw9zNSE+h\n"
    261   "rOMhBrzbbsJluUP3gmd8nOKY5MUimoPkxmAXfp2L0il+MPZT/ZEmo11q0k6J2jfG\n"
    262   "UBQ+oZW9ahNZ9gCDjbYlBblo/mqTai+LdeLO3qk53d0zrZKXvCO6sA3uKpG2WR+g\n"
    263   "+sNKxfYpIHCpanqBU6O+degIV/+WKy3nQ2Fwp7K5HUNj1u0pg0QQ18yf68LTnKFU\n"
    264   "HFjZmmaaopWki5wKSBieHivzQy6w+04HSTogHHRK/y/UcoJNSG7xnHmoPPo1vLT8\n"
    265   "CMRIYnSSgU3wJ43XBJ80WxrC2dcoZjV2XZz+XdQwCD4ZrC1ihykcAmiQA+sauNm7\n"
    266   "dztOMkGzAgMBAAECggEAIbKDzlvXDG/YkxnJqrKXt+yAmak4mNQuNP+YSCEdHSBz\n"
    267   "+SOILa6MbnvqVETX5grOXdFp7SWdfjZiTj2g6VKOJkSA7iKxHRoVf2DkOTB3J8np\n"
    268   "XZd8YaRdMGKVV1O2guQ20Dxd1RGdU18k9YfFNsj4Jtw5sTFTzHr1P0n9ybV9xCXp\n"
    269   "znSxVfRg8U6TcMHoRDJR9EMKQMO4W3OQEmreEPoGt2/+kMuiHjclxLtbwDxKXTLP\n"
    270   "pD0gdg3ibvlufk/ccKl/yAglDmd0dfW22oS7NgvRKUve7tzDxY1Q6O5v8BCnLFSW\n"
    271   "D+z4hS1PzooYRXRkM0xYudvPkryPyu+1kEpw3fNsoQKBgQDRfXJo82XQvlX8WPdZ\n"
    272   "Ts3PfBKKMVu3Wf8J3SYpuvYT816qR3ot6e4Ivv5ZCQkdDwzzBKe2jAv6JddMJIhx\n"
    273   "pkGHc0KKOodd9HoBewOd8Td++hapJAGaGblhL5beIidLKjXDjLqtgoHRGlv5Cojo\n"
    274   "zHa7Viel1eOPPcBumhp83oJ+mQKBgQDC6PmdETZdrW3QPm7ZXxRzF1vvpC55wmPg\n"
    275   "pRfTRM059jzRzAk0QiBgVp3yk2a6Ob3mB2MLfQVDgzGf37h2oO07s5nspSFZTFnM\n"
    276   "KgSjFy0xVOAVDLe+0VpbmLp1YUTYvdCNowaoTE7++5rpePUDu3BjAifx07/yaSB+\n"
    277   "W+YPOfOuKwKBgQCGK6g5G5qcJSuBIaHZ6yTZvIdLRu2M8vDral5k3793a6m3uWvB\n"
    278   "OFAh/eF9ONJDcD5E7zhTLEMHhXDs7YEN+QODMwjs6yuDu27gv97DK5j1lEsrLUpx\n"
    279   "XgRjAE3KG2m7NF+WzO1K74khWZaKXHrvTvTEaxudlO3X8h7rN3u7ee9uEQKBgQC2\n"
    280   "wI1zeTUZhsiFTlTPWfgppchdHPs6zUqq0wFQ5Zzr8Pa72+zxY+NJkU2NqinTCNsG\n"
    281   "ePykQ/gQgk2gUrt595AYv2De40IuoYk9BlTMuql0LNniwsbykwd/BOgnsSlFdEy8\n"
    282   "0RQn70zOhgmNSg2qDzDklJvxghLi7zE5aV9//V1/ewKBgFRHHZN1a8q/v8AAOeoB\n"
    283   "ROuXfgDDpxNNUKbzLL5MO5odgZGi61PBZlxffrSOqyZoJkzawXycNtoBP47tcVzT\n"
    284   "QPq5ZOB3kjHTcN7dRLmPWjji9h4O3eHCX67XaPVMSWiMuNtOZIg2an06+jxGFhLE\n"
    285   "qdJNJ1DkyUc9dN2cliX4R+rG\n"
    286   "-----END PRIVATE KEY-----\n";
    287 
    288 
    289 static const char srv_signed_cert_pem[] =
    290   "-----BEGIN CERTIFICATE-----\n"
    291   "MIIFSzCCAzOgAwIBAgIBBDANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCUlUx\n"
    292   "DzANBgNVBAgMBk1vc2NvdzEPMA0GA1UEBwwGTW9zY293MRswGQYDVQQKDBJ0ZXN0\n"
    293   "LWxpYm1pY3JvaHR0cGQxITAfBgkqhkiG9w0BCQEWEm5vYm9keUBleGFtcGxlLm9y\n"
    294   "ZzEQMA4GA1UEAwwHdGVzdC1DQTAgFw0yMjA0MjAxODQzMDJaGA8yMTIyMDMyNjE4\n"
    295   "NDMwMlowZTELMAkGA1UEBhMCUlUxDzANBgNVBAgMBk1vc2NvdzEPMA0GA1UEBwwG\n"
    296   "TW9zY293MRswGQYDVQQKDBJ0ZXN0LWxpYm1pY3JvaHR0cGQxFzAVBgNVBAMMDnRl\n"
    297   "c3QtbWhkc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn3+2\n"
    298   "psPczUhPoazjIQa8227CZblD94JnfJzimOTFIpqD5MZgF36di9IpfjD2U/2RJqNd\n"
    299   "atJOido3xlAUPqGVvWoTWfYAg422JQW5aP5qk2ovi3Xizt6pOd3dM62Sl7wjurAN\n"
    300   "7iqRtlkfoPrDSsX2KSBwqWp6gVOjvnXoCFf/list50NhcKeyuR1DY9btKYNEENfM\n"
    301   "n+vC05yhVBxY2ZpmmqKVpIucCkgYnh4r80MusPtOB0k6IBx0Sv8v1HKCTUhu8Zx5\n"
    302   "qDz6Nby0/AjESGJ0koFN8CeN1wSfNFsawtnXKGY1dl2c/l3UMAg+GawtYocpHAJo\n"
    303   "kAPrGrjZu3c7TjJBswIDAQABo4HmMIHjMAsGA1UdDwQEAwIFoDAMBgNVHRMBAf8E\n"
    304   "AjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMBMDEGA1UdEQQqMCiCDnRlc3QtbWhk\n"
    305   "c2VydmVyhwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMB0GA1UdDgQWBBQ57Z06WJae\n"
    306   "8fJIHId4QGx/HsRgDDAoBglghkgBhvhCAQ0EGxYZVGVzdCBsaWJtaWNyb2h0dHBk\n"
    307   "IHNlcnZlcjARBglghkgBhvhCAQEEBAMCBkAwHwYDVR0jBBgwFoAUWHVDwKVqMcOF\n"
    308   "Nd0arI3/QB3W6SwwDQYJKoZIhvcNAQELBQADggIBAI7Lggm/XzpugV93H5+KV48x\n"
    309   "X+Ct8unNmPCSzCaI5hAHGeBBJpvD0KME5oiJ5p2wfCtK5Dt9zzf0S0xYdRKqU8+N\n"
    310   "aKIvPoU1hFixXLwTte1qOp6TviGvA9Xn2Fc4n36dLt6e9aiqDnqPbJgBwcVO82ll\n"
    311   "HJxVr3WbrAcQTB3irFUMqgAke/Cva9Bw79VZgX4ghb5EnejDzuyup4pHGzV10Myv\n"
    312   "hdg+VWZbAxpCe0S4eKmstZC7mWsFCLeoRTf/9Pk1kQ6+azbTuV/9QOBNfFi8QNyb\n"
    313   "18jUjmm8sc2HKo8miCGqb2sFqaGD918hfkWmR+fFkzQ3DZQrT+eYbKq2un3k0pMy\n"
    314   "UySy8SRn1eadfab+GwBVb68I9TrPRMrJsIzysNXMX4iKYl2fFE/RSNnaHtPw0C8y\n"
    315   "B7memyxPRl+H2xg6UjpoKYh3+8e44/XKm0rNIzXjrwA8f8gnw2TbqmMDkj1YqGnC\n"
    316   "SCj5A27zUzaf2pT/YsnQXIWOJjVvbEI+YKj34wKWyTrXA093y8YI8T3mal7Kr9YM\n"
    317   "WiIyPts0/aVeziM0Gunglz+8Rj1VesL52FTurobqusPgM/AME82+qb/qnxuPaCKj\n"
    318   "OT1qAbIblaRuWqCsid8BzP7ZQiAnAWgMRSUg1gzDwSwRhrYQRRWAyn/Qipzec+27\n"
    319   "/w0gW9EVWzFhsFeGEssi\n"
    320   "-----END CERTIFICATE-----\n";
    321 
    322 
    323 static const char srv_self_signed_cert_pem[] =
    324   "-----BEGIN CERTIFICATE-----\n"
    325   "MIIDJzCCAg+gAwIBAgIUOKf6e6Heee2XA+yF5St3t+fVM40wDQYJKoZIhvcNAQEF\n"
    326   "BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MCAXDTIyMTAxMDA4MzQ0N1oYDzIxMjIw\n"
    327   "OTE2MDgzNDQ3WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB\n"
    328   "AQUAA4IBDwAwggEKAoIBAQClivgF8Xq0ekQli++0l7Q5JFwJCuLf04Cb1UKIS80U\n"
    329   "CfphFd1ILJepNw4bWR3OV1sRI1vFiw6LnCz53vOwVNyiZ+sMGi4bDX4AV9Xd+F83\n"
    330   "xhG8AjOmKTayW0TxSIvt47Qd5S/4fgraxMtvqrRRBen30iKOwX7uNF/4dYb9vdin\n"
    331   "OldV/e8uzbqSurMGkNDznOeSaNBmdO/7x0VMFZM2hwmHyiiw75/j4BhUlLCcMEvK\n"
    332   "oN+YHNCNcTt3Qm1vVuiGXmh9QreOV09Gc1SzAltxF2gmI0jzw8r/duz18QXMNsMw\n"
    333   "El/Ah4+02gR70L7qlgttN1NPU3RJpK/L34J7yg649wHTAgMBAAGjbzBtMB0GA1Ud\n"
    334   "DgQWBBROVferD+YYcV1YEnFgC0jYm5X9BjAfBgNVHSMEGDAWgBROVferD+YYcV1Y\n"
    335   "EnFgC0jYm5X9BjAPBgNVHRMBAf8EBTADAQH/MBoGA1UdEQQTMBGCCWxvY2FsaG9z\n"
    336   "dIcEfwAAATANBgkqhkiG9w0BAQUFAAOCAQEAoRbozsm5xXdNX3VO++s2LMzw5KM9\n"
    337   "RpIInHNkMJbnyLJFKJ8DF7nTxSGCA38YMkX3tphPNKZXbg+V64Dqr/XpzOVyiinU\n"
    338   "7hIwyUdSSKKyErZxIWR97lY6Q3SOyPAg8ZElbtvSsSzmd772VE23VTXGDi7AW0PQ\n"
    339   "hag9N2EEnHURMvID15O+UXyFpDdyUyQIbx3HuswsGDH9xBTm4irLyrZwO0KwKg5a\n"
    340   "JBeUiPs0SYRRfn9/MoE6VwAnmOCg3LLR6ZPU3hQtTPLHj2Op1g5fey3X3X6lC+JC\n"
    341   "K6dNZc1zBFPz8KANGUsFYbmoP2bvAAA+6KwCnZZEflUgE7/HFEmQhVOezw==\n"
    342   "-----END CERTIFICATE-----\n";
    343 
    344 
    345 static const char srv_self_signed_key_pem[] =
    346   "-----BEGIN PRIVATE KEY-----\n"
    347   "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQClivgF8Xq0ekQl\n"
    348   "i++0l7Q5JFwJCuLf04Cb1UKIS80UCfphFd1ILJepNw4bWR3OV1sRI1vFiw6LnCz5\n"
    349   "3vOwVNyiZ+sMGi4bDX4AV9Xd+F83xhG8AjOmKTayW0TxSIvt47Qd5S/4fgraxMtv\n"
    350   "qrRRBen30iKOwX7uNF/4dYb9vdinOldV/e8uzbqSurMGkNDznOeSaNBmdO/7x0VM\n"
    351   "FZM2hwmHyiiw75/j4BhUlLCcMEvKoN+YHNCNcTt3Qm1vVuiGXmh9QreOV09Gc1Sz\n"
    352   "AltxF2gmI0jzw8r/duz18QXMNsMwEl/Ah4+02gR70L7qlgttN1NPU3RJpK/L34J7\n"
    353   "yg649wHTAgMBAAECggEAERbbCtYGakoy7cNX8Ac3Kiz4OVC/4gZWAQBPeX2FwrtS\n"
    354   "9yHIMbK0x1mxIZ6eBpabBpZlW2vDCSOKuxLKiloAWt2qdJnhR5apesSWhe8leT7/\n"
    355   "xq5dgZpAlMH6SIRKObknd2yY+qicW0A0licDrVeUcypkueL8xP9wJtiPInOuQXkI\n"
    356   "QROhB13eStRuRKYwOn5gtwAHJ+J1DFKKiqpBOkrSYf4625StGegJO9+bjK0ei+0W\n"
    357   "tp6unpiwA/lXTgz6Xim1Z3fzWs4XjFgVKzK5s/6yBJjr8spHX6lv7QsahP4w6HZ/\n"
    358   "VcRxP6cJNd/otiTEtJXpbxiiyccwXm/AOcOn22P1cQKBgQDAnY/0G/ap/G98pneE\n"
    359   "suzNXhWOQ8JoL8d66Io8vwTvfiJggfgUcwblI7pPCrSlaZMR7/q6JImE53lZtPk8\n"
    360   "eI3c9lN0ocr8E7+huDpYdk7cMYj9SuxySsXoMLiMqzHFi+NcIhKMF56kk6a5CFCt\n"
    361   "yP1Ofy76LVweGE3XvTwpwE7wUQKBgQDcBLyH1cC71s0I0Gz28AyELV9hPhasjAKO\n"
    362   "12CVbeBVTPd+28uk/3o80wSrTksc6H5ehAA2aTvrb4OhwssWNL+D0fS8YK2cJ3V0\n"
    363   "FJxGAM266+vC4d/8jRTHJnc+6PP3ix5t6vAt+K2Y0fePtefLqf4ebgXx/ODAj3J2\n"
    364   "aZKBldjK4wKBgGIRFpTLk/eR/dUyEBHw4x3gdAsdtqJDCUYrlQ4+ly20Q55tLbiD\n"
    365   "pBQP77CEm9rH+MgeLcKODbIsBB3HRUojet7wTydHpMhY6a1V1ebqPVZgpgWIGwBJ\n"
    366   "z59bBusf0lRo15Y2Bslq0SurvSvh7um8NjO8D1fytj7gUumvgC0lq0sxAoGBAI1+\n"
    367   "kkx9IBTtIDER8XGhkTsT/uoHxwcyh5abVmbjIclZ1TUFX2L+Vft17ePJVy8BKfvY\n"
    368   "wlY7uShBMBNAteDTDXNV/CGFv0DUc4myk4nFjIkwng9XufeuN3WX/Eo+AF/rXSdt\n"
    369   "VwcJjYLhTWdjoe1tppqlQTeN3HCaEA+s92ZVGvXnAoGAMCXGS6WZl1e5wsHRq0Yy\n"
    370   "8Ef2Wrk620bBjKHolkTfvgfhlvxeZM1sv1ioZGsOeQ0z7O7wdJhvL0M/WAG+3yQj\n"
    371   "HSXp81T1vOICPwNYZf8xcvbLKmvj7rHFt6ZAZF2o4EK8ReZTRyA3DUpBCDY+s3FN\n"
    372   "GmBv0D7N3QP0CT3SzfQrPkc=\n"
    373   "-----END PRIVATE KEY-----\n";
    374 
    375 
    376 static const char dh_params_pem[] =
    377   "-----BEGIN DH PARAMETERS-----\n"
    378   "MIIBDAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n"
    379   "+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n"
    380   "87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n"
    381   "YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n"
    382   "7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n"
    383   "ssbzSibBsu/6iGtCOGEoXJf//////////wIBAgICAQA=\n"
    384   "-----END DH PARAMETERS-----\n";
    385 
    386 /** A PEM blob whose armour is fine but whose payload is not base64. */
    387 static const char garbage_cert_pem[] =
    388   "-----BEGIN CERTIFICATE-----\n"
    389   "this is not base64 at all, not even close !!!! ????\n"
    390   "-----END CERTIFICATE-----\n";
    391 
    392 static const char garbage_key_pem[] =
    393   "-----BEGIN PRIVATE KEY-----\n"
    394   "@@@@ neither is this @@@@\n"
    395   "-----END PRIVATE KEY-----\n";
    396 
    397 /** Correct base64, but the armour never ends. */
    398 static const char truncated_cert_pem[] =
    399   "-----BEGIN CERTIFICATE-----\n"
    400   "MIIFSzCCAzOgAwIBAgIBBDANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCUlUx\n"
    401   "DzANBgNVBAgMBk1vc2NvdzEPMA0GA1UEBwwGTW9zY293MRswGQYDVQQKDBJ0ZXN0\n";
    402 
    403 static const char truncated_key_pem[] =
    404   "-----BEGIN PRIVATE KEY-----\n"
    405   "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCff7amw9zNSE+h\n";
    406 
    407 /** Base64 of a certificate, but with no PEM armour at all. */
    408 static const char no_armour_pem[] =
    409   "MIIFSzCCAzOgAwIBAgIBBDANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCUlUx\n"
    410   "DzANBgNVBAgMBk1vc2NvdzEPMA0GA1UEBwwGTW9zY293MRswGQYDVQQKDBJ0ZXN0\n";
    411 
    412 static const char garbage_dh_pem[] =
    413   "-----BEGIN DH PARAMETERS-----\n"
    414   "not-dh-parameters\n"
    415   "-----END DH PARAMETERS-----\n";
    416 
    417 /**
    418  * PEM blobs assembled from the fuzzer's own bytes, see cred_tbl entries
    419  * 12 and 13.  Static so that the pointer handed to MHD stays valid for
    420  * the whole lifetime of the daemon.
    421  */
    422 static char fuzz_cert_pem[FUZZ_PEM_BODY_MAX + 128];
    423 static char fuzz_key_pem[FUZZ_PEM_BODY_MAX + 128];
    424 
    425 
    426 /**
    427  * A certificate/key pair for #MHD_OPTION_HTTPS_MEM_CERT and
    428  * #MHD_OPTION_HTTPS_MEM_KEY.  A NULL member means "do not pass the
    429  * option at all", which is a configuration MHD has to reject cleanly.
    430  */
    431 struct cred_pair
    432 {
    433   const char *cert;
    434   const char *key;
    435 };
    436 
    437 static const struct cred_pair cred_tbl[] = {
    438   { srv_signed_cert_pem, srv_signed_key_pem },        /*  0 valid, CA signed */
    439   { srv_self_signed_cert_pem, srv_self_signed_key_pem }, /* 1 valid, self signed */
    440   { srv_signed_cert_pem, srv_self_signed_key_pem },   /*  2 key does not match */
    441   { srv_self_signed_cert_pem, srv_signed_key_pem },   /*  3 key does not match */
    442   { srv_signed_cert_pem, NULL },                      /*  4 certificate only */
    443   { NULL, srv_signed_key_pem },                       /*  5 key only */
    444   { NULL, NULL },                                     /*  6 neither */
    445   { "", "" },                                         /*  7 empty strings */
    446   { truncated_cert_pem, srv_signed_key_pem },         /*  8 truncated armour */
    447   { srv_signed_cert_pem, truncated_key_pem },         /*  9 truncated armour */
    448   { garbage_cert_pem, garbage_key_pem },              /* 10 armour, no base64 */
    449   { no_armour_pem, srv_signed_key_pem },              /* 11 base64, no armour */
    450   { fuzz_cert_pem, srv_signed_key_pem },              /* 12 PEM from the input */
    451   { srv_signed_cert_pem, fuzz_key_pem },              /* 13 PEM from the input */
    452   { fuzz_cert_pem, fuzz_key_pem },                    /* 14 PEM from the input */
    453   { srv_signed_cert_pem, srv_signed_key_pem }         /* 15 valid (bias) */
    454 };
    455 
    456 #define CRED_COUNT (sizeof (cred_tbl) / sizeof (cred_tbl[0]))
    457 
    458 /**
    459  * Priority strings.  The first entries are the ones a real server would
    460  * use, the rest are what MHD has to reject without falling over.  MHD
    461  * hands these to gnutls_priority_init() (or appends them to its own
    462  * base string) and fails daemon startup if GnuTLS does not like them.
    463  */
    464 static const char *const prio_tbl[] = {
    465   "NORMAL",
    466   "NORMAL:-VERS-ALL:+VERS-TLS1.3",
    467   "NORMAL:-VERS-ALL:+VERS-TLS1.2",
    468   "SECURE128",
    469   "PERFORMANCE",
    470   "@LIBMICROHTTPD",
    471   "@SYSTEM",
    472   "NONE",
    473   "",
    474   "BOGUS-PRIORITY-STRING",
    475   "NORMAL:!!!",
    476   "NORMAL:-VERS-ALL",
    477   "NORMAL:+ANON-ECDH",
    478   "NORMAL:%SERVER_PRECEDENCE",
    479   "SECURE256:-CIPHER-ALL",
    480   ":::::"
    481 };
    482 
    483 #define PRIO_COUNT (sizeof (prio_tbl) / sizeof (prio_tbl[0]))
    484 
    485 /** Priority strings offered to the *client* side. */
    486 static const char *const client_prio_tbl[CLIENT_PRIO_COUNT] = {
    487   "NORMAL",
    488   "NORMAL:-VERS-ALL:+VERS-TLS1.3",
    489   "NORMAL:-VERS-ALL:+VERS-TLS1.2",
    490   "PERFORMANCE"
    491 };
    492 
    493 /**
    494  * Credential types.  Only GNUTLS_CRD_CERTIFICATE and GNUTLS_CRD_PSK are
    495  * accepted by MHD_TLS_init(); everything else must make daemon startup
    496  * fail rather than reach the MHD_PANIC() in new_connection_prepare_().
    497  */
    498 static const int cred_type_tbl[] = {
    499   (int) GNUTLS_CRD_CERTIFICATE,
    500   (int) GNUTLS_CRD_PSK,
    501   (int) GNUTLS_CRD_ANON,
    502   (int) GNUTLS_CRD_SRP,
    503   (int) GNUTLS_CRD_IA,
    504   (int) GNUTLS_CRD_CERTIFICATE,
    505   99,
    506   -1
    507 };
    508 
    509 #define CRED_TYPE_COUNT (sizeof (cred_type_tbl) / sizeof (cred_type_tbl[0]))
    510 
    511 static const size_t mem_limit_tbl[] = {
    512   0 /* MHD default */, 256, 512, 1024, 1400, 1500, 2048, 4096, 8192, 32768,
    513   0, 1024, 2048, 4096, 16384, 0
    514 };
    515 
    516 #define MEM_LIMIT_COUNT (sizeof (mem_limit_tbl) / sizeof (mem_limit_tbl[0]))
    517 
    518 static const char https_key_password[] = "not-the-password";
    519 
    520 
    521 /* ------------------------------------------------------------------ */
    522 /* Per-iteration configuration                                         */
    523 /* ------------------------------------------------------------------ */
    524 
    525 /** Behaviour of the SNI callback, selected by bits 3-5 of byte 3. */
    526 enum sni_behaviour
    527 {
    528   SNI_ALWAYS_OK = 0,      /**< always answer with the signed pair */
    529   SNI_FAIL,               /**< always answer -1 */
    530   SNI_EMPTY,              /**< answer 0 with an empty certificate list */
    531   SNI_BY_NAME,            /**< look the server name up, -1 if unknown */
    532   SNI_MISMATCH,           /**< answer with a key that is not the cert's */
    533   SNI_NO_KEY,             /**< answer 0, certificate but no key */
    534   SNI_SELF_SIGNED,        /**< always answer with the self-signed pair */
    535   SNI_BEHAVIOUR_COUNT
    536 };
    537 
    538 /** Client behaviour, selected by bits 0-1 of byte 4. */
    539 enum client_mode
    540 {
    541   CLIENT_RAW = 0,         /**< raw bytes straight at the TLS socket */
    542   CLIENT_TLS,             /**< a real GnuTLS client */
    543   CLIENT_TLS_ABANDON,     /**< a real client that stops mid-handshake */
    544   CLIENT_RECORDS          /**< raw bytes shaped like TLS records */
    545 };
    546 
    547 struct fuzz_cfg
    548 {
    549   /* ---- daemon ---- */
    550   const char *cert;
    551   const char *key;
    552   int use_tls;                 /**< set MHD_USE_TLS at all */
    553   int use_trust;
    554   int trust_garbage;
    555   int use_dhparams;
    556   int dh_garbage;
    557   int use_sni;
    558   int use_prio;
    559   int prio_append;
    560   unsigned int prio_idx;
    561   int use_cred_type;
    562   unsigned int cred_type_idx;
    563   int no_alpn;
    564   int key_password;
    565   int allow_upgrade;
    566   size_t mem_limit;
    567   unsigned int loop_mode;
    568 
    569   /* ---- SNI callback ---- */
    570   enum sni_behaviour sni_mode;
    571 
    572   /* ---- client ---- */
    573   enum client_mode mode;
    574   int client_sni;
    575   int client_cert;
    576   unsigned int client_prio_idx;
    577   int client_bye;
    578   int client_shut_wr;
    579   unsigned int hs_budget;      /**< handshake rounds in CLIENT_TLS_ABANDON */
    580   unsigned int extra_pump;
    581 
    582   /* ---- handler ---- */
    583   unsigned int resp_kind;
    584   int conn_info;
    585   int daemon_info;
    586   int conn_option;
    587   int error_reply;
    588   int resp_header;
    589   int quiesce;
    590 };
    591 
    592 static struct fuzz_cfg cfg;
    593 
    594 /**
    595  * Server names the client can present.  Which one is used comes from
    596  * byte 9 of the input; an op 1 segment overrides it.  MHD itself never
    597  * looks at the name -- GnuTLS parses the extension and the application
    598  * callback reads it back -- so a fixed table costs no MHD coverage.
    599  */
    600 static const char *const sni_name_tbl[] = {
    601   "test-mhdserver",
    602   "localhost",
    603   "mhdhost1",
    604   "nobody.example.org",
    605   "",
    606   "example.org",
    607   "TEST-MHDSERVER",
    608   "a.very.long.name.that.nobody.has.a.certificate.for.example.org"
    609 };
    610 
    611 #define SNI_NAME_COUNT (sizeof (sni_name_tbl) / sizeof (sni_name_tbl[0]))
    612 
    613 /** Server name the next client connection presents. */
    614 static char sni_name[MAX_SNI_LEN + 1];
    615 static size_t sni_name_len;
    616 
    617 /** Bytes received from the daemon during the current iteration. */
    618 static char resp_buf[RESP_BUF_SIZE];
    619 static size_t resp_len;
    620 
    621 /** Statistics, printed at exit with --verbose. */
    622 static unsigned long stat_daemons;
    623 static unsigned long stat_daemons_failed;
    624 static unsigned long stat_connections;
    625 static unsigned long stat_handshakes_ok;
    626 static unsigned long stat_handshakes_failed;
    627 static unsigned long stat_handler_calls;
    628 static unsigned long stat_sni_calls;
    629 static int stats_registered;
    630 
    631 
    632 static void
    633 print_stats (void)
    634 {
    635   if (! fuzz_verbose)
    636     return;
    637   fprintf (stderr,
    638            "%s: daemons=%lu (start failed=%lu) connections=%lu "
    639            "handshakes ok=%lu failed=%lu handler calls=%lu SNI calls=%lu\n",
    640            FUZZ_HARNESS_NAME,
    641            stat_daemons, stat_daemons_failed, stat_connections,
    642            stat_handshakes_ok, stat_handshakes_failed, stat_handler_calls,
    643            stat_sni_calls);
    644 }
    645 
    646 
    647 /* ------------------------------------------------------------------ */
    648 /* The SNI (certificate retrieve) callback                             */
    649 /* ------------------------------------------------------------------ */
    650 
    651 /**
    652  * Certificates for the SNI callback, parsed once and then kept in these
    653  * statics for the whole life of the process: they are configuration, not
    654  * per-iteration state, and re-parsing them on every execution would cost
    655  * more than everything else the harness does.  They are reachable from
    656  * globals, so LeakSanitizer does not count them.
    657  */
    658 struct sni_host
    659 {
    660   const char *name;
    661   const char *cert_pem;
    662   const char *key_pem;
    663   gnutls_pcert_st pcrt;
    664   gnutls_privkey_t key;
    665   int loaded;
    666 };
    667 
    668 static struct sni_host sni_hosts[2] = {
    669   { "test-mhdserver", NULL, NULL, { 0, { NULL, 0 }, 0 }, NULL, 0 },
    670   { "localhost", NULL, NULL, { 0, { NULL, 0 }, 0 }, NULL, 0 }
    671 };
    672 
    673 static int sni_hosts_ready;
    674 
    675 
    676 /**
    677  * @return 0 if the certificates are usable
    678  */
    679 static int
    680 sni_hosts_init (void)
    681 {
    682   unsigned int i;
    683 
    684   if (0 != sni_hosts_ready)
    685     return (1 == sni_hosts_ready) ? 0 : -1;
    686   sni_hosts[0].cert_pem = srv_signed_cert_pem;
    687   sni_hosts[0].key_pem = srv_signed_key_pem;
    688   sni_hosts[1].cert_pem = srv_self_signed_cert_pem;
    689   sni_hosts[1].key_pem = srv_self_signed_key_pem;
    690   sni_hosts_ready = 1;
    691   for (i = 0; i < sizeof (sni_hosts) / sizeof (sni_hosts[0]); i++)
    692   {
    693     struct sni_host *h = &sni_hosts[i];
    694     gnutls_datum_t d;
    695 
    696     d.data = (unsigned char *) (intptr_t) h->cert_pem;
    697     d.size = (unsigned int) strlen (h->cert_pem);
    698     if (GNUTLS_E_SUCCESS !=
    699         gnutls_pcert_import_x509_raw (&h->pcrt, &d, GNUTLS_X509_FMT_PEM, 0))
    700     {
    701       sni_hosts_ready = -1;
    702       continue;
    703     }
    704     if (GNUTLS_E_SUCCESS != gnutls_privkey_init (&h->key))
    705     {
    706       gnutls_pcert_deinit (&h->pcrt);
    707       sni_hosts_ready = -1;
    708       continue;
    709     }
    710     d.data = (unsigned char *) (intptr_t) h->key_pem;
    711     d.size = (unsigned int) strlen (h->key_pem);
    712     if (GNUTLS_E_SUCCESS !=
    713         gnutls_privkey_import_x509_raw (h->key, &d, GNUTLS_X509_FMT_PEM,
    714                                         NULL, 0))
    715     {
    716       gnutls_privkey_deinit (h->key);
    717       h->key = NULL;
    718       gnutls_pcert_deinit (&h->pcrt);
    719       sni_hosts_ready = -1;
    720       continue;
    721     }
    722     h->loaded = 1;
    723   }
    724   return (1 == sni_hosts_ready) ? 0 : -1;
    725 }
    726 
    727 
    728 /**
    729  * #MHD_OPTION_HTTPS_CERT_CALLBACK.  Deliberately badly behaved for most
    730  * of the settings of @e cfg.sni_mode: an application callback that fails
    731  * or answers with nothing is exactly the case MHD has to survive.
    732  */
    733 static int
    734 sni_callback (gnutls_session_t session,
    735               const gnutls_datum_t *req_ca_dn,
    736               int nreqs,
    737               const gnutls_pk_algorithm_t *pk_algos,
    738               int pk_algos_length,
    739               gnutls_pcert_st **pcert,
    740               unsigned int *pcert_length,
    741               gnutls_privkey_t *pkey)
    742 {
    743   char name[MAX_SNI_LEN + 1];
    744   size_t name_len = sizeof (name);
    745   unsigned int type;
    746   unsigned int i;
    747 
    748   (void) req_ca_dn;
    749   (void) nreqs;
    750   (void) pk_algos;
    751   (void) pk_algos_length;
    752   stat_sni_calls++;
    753   if (! sni_hosts[0].loaded)
    754     return -1;
    755   switch (cfg.sni_mode)
    756   {
    757   case SNI_FAIL:
    758     return -1;
    759   case SNI_EMPTY:
    760     *pcert = NULL;
    761     *pcert_length = 0;
    762     *pkey = NULL;
    763     return 0;
    764   case SNI_NO_KEY:
    765     *pcert = &sni_hosts[0].pcrt;
    766     *pcert_length = 1;
    767     *pkey = NULL;
    768     return 0;
    769   case SNI_MISMATCH:
    770     if (! sni_hosts[1].loaded)
    771       return -1;
    772     *pcert = &sni_hosts[0].pcrt;
    773     *pcert_length = 1;
    774     *pkey = sni_hosts[1].key;
    775     return 0;
    776   case SNI_SELF_SIGNED:
    777     if (! sni_hosts[1].loaded)
    778       return -1;
    779     *pcert = &sni_hosts[1].pcrt;
    780     *pcert_length = 1;
    781     *pkey = sni_hosts[1].key;
    782     return 0;
    783   case SNI_BY_NAME:
    784     if (GNUTLS_E_SUCCESS !=
    785         gnutls_server_name_get (session, name, &name_len, &type, 0))
    786       return -1;
    787     for (i = 0; i < sizeof (sni_hosts) / sizeof (sni_hosts[0]); i++)
    788       if ( (sni_hosts[i].loaded) &&
    789            (0 == strncmp (name, sni_hosts[i].name, name_len)) )
    790       {
    791         *pcert = &sni_hosts[i].pcrt;
    792         *pcert_length = 1;
    793         *pkey = sni_hosts[i].key;
    794         return 0;
    795       }
    796     return -1;
    797   case SNI_ALWAYS_OK:
    798   case SNI_BEHAVIOUR_COUNT:
    799   default:
    800     break;
    801   }
    802   *pcert = &sni_hosts[0].pcrt;
    803   *pcert_length = 1;
    804   *pkey = sni_hosts[0].key;
    805   return 0;
    806 }
    807 
    808 
    809 /* ------------------------------------------------------------------ */
    810 /* The application                                                     */
    811 /* ------------------------------------------------------------------ */
    812 
    813 static const char resp_body[] = "hello world over TLS";
    814 
    815 
    816 static enum MHD_Result
    817 ahc (void *cls,
    818      struct MHD_Connection *connection,
    819      const char *url,
    820      const char *method,
    821      const char *version,
    822      const char *upload_data,
    823      size_t *upload_data_size,
    824      void **req_cls)
    825 {
    826   static int marker;
    827   struct MHD_Response *r;
    828   enum MHD_Result ret;
    829 
    830   (void) cls;
    831   (void) url;
    832   (void) method;
    833   (void) version;
    834   (void) upload_data;
    835   stat_handler_calls++;
    836   if (NULL == *req_cls)
    837   {
    838     /* first call: MHD only wants to know that we are interested */
    839     *req_cls = &marker;
    840     return MHD_YES;
    841   }
    842   if (0 != *upload_data_size)
    843   {
    844     /* discard the request body */
    845     *upload_data_size = 0;
    846     return MHD_YES;
    847   }
    848   if (cfg.conn_info)
    849   {
    850     /* The TLS-specific members of MHD_ConnectionInfo; all three answer
    851        NULL on a connection without a session, which is a state this
    852        harness can produce. */
    853     (void) MHD_get_connection_info (connection,
    854                                     MHD_CONNECTION_INFO_CIPHER_ALGO);
    855     (void) MHD_get_connection_info (connection,
    856                                     MHD_CONNECTION_INFO_PROTOCOL);
    857     (void) MHD_get_connection_info (connection,
    858                                     MHD_CONNECTION_INFO_GNUTLS_SESSION);
    859     (void) MHD_get_connection_info (connection,
    860                                     MHD_CONNECTION_INFO_GNUTLS_CLIENT_CERT);
    861     (void) MHD_get_connection_info (connection,
    862                                     MHD_CONNECTION_INFO_CLIENT_ADDRESS);
    863     (void) MHD_get_connection_info (connection,
    864                                     MHD_CONNECTION_INFO_CONNECTION_FD);
    865   }
    866   if (cfg.conn_option)
    867     (void) MHD_set_connection_option (connection,
    868                                       MHD_CONNECTION_OPTION_TIMEOUT,
    869                                       (unsigned int) 0);
    870   switch (cfg.resp_kind)
    871   {
    872   case 1:
    873     r = MHD_create_response_from_buffer_copy (sizeof (resp_body) - 1,
    874                                               resp_body);
    875     break;
    876   case 2:
    877     r = MHD_create_response_empty (MHD_RF_NONE);
    878     break;
    879   case 3:
    880     r = MHD_create_response_from_buffer_static (0, "");
    881     break;
    882   case 0:
    883   default:
    884     r = MHD_create_response_from_buffer_static (sizeof (resp_body) - 1,
    885                                                 resp_body);
    886     break;
    887   }
    888   if (NULL == r)
    889     return MHD_NO;
    890   if (cfg.resp_header)
    891     (void) MHD_add_response_header (r, "X-Fuzz", "tls");
    892   ret = MHD_queue_response (connection,
    893                             cfg.error_reply
    894                             ? MHD_HTTP_FORBIDDEN
    895                             : MHD_HTTP_OK,
    896                             r);
    897   MHD_destroy_response (r);
    898   return ret;
    899 }
    900 
    901 
    902 static void
    903 panic_cb (void *cls,
    904           const char *file,
    905           unsigned int line,
    906           const char *reason)
    907 {
    908   char msg[512];
    909 
    910   (void) cls;
    911   (void) snprintf (msg, sizeof (msg),
    912                    "MHD_PANIC() reached at %s:%u: %s",
    913                    (NULL != file) ? file : "?",
    914                    line,
    915                    (NULL != reason) ? reason : "?");
    916   fuzz_report_finding (msg);
    917 }
    918 
    919 
    920 /* ------------------------------------------------------------------ */
    921 /* Driving the daemon                                                  */
    922 /* ------------------------------------------------------------------ */
    923 
    924 /**
    925  * Advance the daemon by one cycle, through the event-loop API selected
    926  * by byte 5 of the input.  The select() timeout is always zero: the
    927  * harness is single threaded, whatever the daemon is waiting for has
    928  * already been written into the socketpair, and blocking would only burn
    929  * wall clock.
    930  */
    931 static void
    932 run_once (struct MHD_Daemon *d)
    933 {
    934   fd_set rs;
    935   fd_set ws;
    936   fd_set es;
    937   MHD_socket max_fd = MHD_INVALID_SOCKET;
    938   struct timeval tv;
    939 
    940   if (0 == cfg.loop_mode)
    941   {
    942     (void) MHD_run (d);
    943     return;
    944   }
    945   FD_ZERO (&rs);
    946   FD_ZERO (&ws);
    947   FD_ZERO (&es);
    948   if (1 == cfg.loop_mode)
    949   {
    950     /* Parenthesised so that the real v1 function is called: microhttpd.h
    951        also defines MHD_get_fdset as a macro forwarding to
    952        MHD_get_fdset2.  Same trick for MHD_run_from_select below. */
    953     if (MHD_YES != (MHD_get_fdset) (d, &rs, &ws, &es, &max_fd))
    954     {
    955       (void) MHD_run (d);
    956       return;
    957     }
    958   }
    959   else
    960   {
    961     if (MHD_YES != MHD_get_fdset2 (d, &rs, &ws, &es, &max_fd,
    962                                    (unsigned int) FD_SETSIZE))
    963     {
    964       (void) MHD_run (d);
    965       return;
    966     }
    967   }
    968   tv.tv_sec = 0;
    969   tv.tv_usec = 0;
    970   if (MHD_INVALID_SOCKET != max_fd)
    971     (void) select ((int) max_fd + 1, &rs, &ws, &es, &tv);
    972   if (1 == cfg.loop_mode)
    973     (void) (MHD_run_from_select) (d, &rs, &ws, &es);
    974   else
    975     (void) MHD_run_from_select2 (d, &rs, &ws, &es, (unsigned int) FD_SETSIZE);
    976 }
    977 
    978 
    979 /* ------------------------------------------------------------------ */
    980 /* The in-process TLS client                                           */
    981 /* ------------------------------------------------------------------ */
    982 
    983 struct tls_client
    984 {
    985   gnutls_session_t sess;                    /**< NULL in the raw modes */
    986   gnutls_certificate_credentials_t cred;
    987   int fd;                                   /**< our end of the socketpair */
    988   int hs_done;
    989   int dead;
    990 };
    991 
    992 
    993 static void
    994 pump (struct MHD_Daemon *d,
    995       unsigned int rounds)
    996 {
    997   unsigned int i;
    998 
    999   for (i = 0; i < rounds; i++)
   1000     run_once (d);
   1001 }
   1002 
   1003 
   1004 /**
   1005  * Read whatever the daemon has produced so far.  In the raw modes this
   1006  * is a plain recv(); with a real client it goes through GnuTLS, which is
   1007  * what actually drives MHD's send path and its TLS shutdown handling.
   1008  */
   1009 static void
   1010 tc_drain (struct tls_client *tc)
   1011 {
   1012   unsigned int i;
   1013   char tmp[4096];
   1014 
   1015   if (0 > tc->fd)
   1016     return;
   1017   if (NULL == tc->sess)
   1018   {
   1019     for (;;)
   1020     {
   1021       ssize_t n = recv (tc->fd, tmp, sizeof (tmp), MSG_DONTWAIT);
   1022 
   1023       if (0 >= n)
   1024         break;
   1025       if (resp_len + (size_t) n < RESP_BUF_SIZE)
   1026       {
   1027         memcpy (resp_buf + resp_len, tmp, (size_t) n);
   1028         resp_len += (size_t) n;
   1029       }
   1030     }
   1031     return;
   1032   }
   1033   if (tc->dead || (! tc->hs_done))
   1034     return;
   1035   for (i = 0; i < 8; i++)
   1036   {
   1037     ssize_t n = gnutls_record_recv (tc->sess, tmp, sizeof (tmp));
   1038 
   1039     if (0 < n)
   1040     {
   1041       if (resp_len + (size_t) n < RESP_BUF_SIZE)
   1042       {
   1043         memcpy (resp_buf + resp_len, tmp, (size_t) n);
   1044         resp_len += (size_t) n;
   1045       }
   1046       continue;
   1047     }
   1048     if (0 == n)
   1049       break;                    /* peer closed the TLS connection */
   1050     if ( (GNUTLS_E_AGAIN == n) ||
   1051          (GNUTLS_E_INTERRUPTED == n) )
   1052       break;
   1053     if (0 != gnutls_error_is_fatal ((int) n))
   1054       tc->dead = 1;
   1055     break;
   1056   }
   1057 }
   1058 
   1059 
   1060 static void
   1061 pump_and_drain (struct MHD_Daemon *d,
   1062                 struct tls_client *tc,
   1063                 unsigned int rounds)
   1064 {
   1065   unsigned int i;
   1066 
   1067   for (i = 0; i < rounds; i++)
   1068   {
   1069     run_once (d);
   1070     tc_drain (tc);
   1071   }
   1072 }
   1073 
   1074 
   1075 /**
   1076  * Let the client and the daemon take turns at the handshake until it
   1077  * completes, fails, or @a rounds is exhausted.  Exhausting @a rounds on
   1078  * purpose (client mode 2) is what leaves MHD's connection parked in
   1079  * #MHD_TLS_CONN_HANDSHAKING.
   1080  */
   1081 static void
   1082 tc_handshake (struct MHD_Daemon *d,
   1083               struct tls_client *tc,
   1084               unsigned int rounds)
   1085 {
   1086   unsigned int i;
   1087 
   1088   if ( (NULL == tc->sess) ||
   1089        (0 != tc->dead) ||
   1090        (0 != tc->hs_done) )
   1091     return;
   1092   for (i = 0; i < rounds; i++)
   1093   {
   1094     int ret = gnutls_handshake (tc->sess);
   1095 
   1096     if (GNUTLS_E_SUCCESS == ret)
   1097     {
   1098       tc->hs_done = 1;
   1099       stat_handshakes_ok++;
   1100       return;
   1101     }
   1102     if (0 != gnutls_error_is_fatal (ret))
   1103     {
   1104       tc->dead = 1;
   1105       stat_handshakes_failed++;
   1106       return;
   1107     }
   1108     /* GNUTLS_E_AGAIN / GNUTLS_E_INTERRUPTED / a warning alert: give the
   1109        daemon a chance to answer. */
   1110     run_once (d);
   1111   }
   1112 }
   1113 
   1114 
   1115 /**
   1116  * Open a fresh connection: a socketpair, one end handed to MHD with
   1117  * MHD_add_connection(), the other end ours.  With a real client the
   1118  * GnuTLS session is set up here too, but the handshake itself is driven
   1119  * by tc_handshake().
   1120  *
   1121  * @return 0 on success
   1122  */
   1123 static int
   1124 tc_open (struct MHD_Daemon *d,
   1125          struct tls_client *tc)
   1126 {
   1127   int sv[2];
   1128   struct sockaddr_in sa;
   1129   int fl;
   1130 #if GNUTLS_VERSION_NUMBER >= 0x030500
   1131   gnutls_init_flags_t flags;
   1132 #else
   1133   unsigned int flags;
   1134 #endif
   1135 
   1136   memset (tc, 0, sizeof (*tc));
   1137   tc->fd = -1;
   1138   if (0 != socketpair (AF_UNIX, SOCK_STREAM, 0, sv))
   1139     return -1;
   1140   memset (&sa, 0, sizeof (sa));
   1141   sa.sin_family = AF_INET;
   1142   sa.sin_port = htons (44444);
   1143   sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
   1144   if (MHD_YES != MHD_add_connection (d,
   1145                                      (MHD_socket) sv[1],
   1146                                      (const struct sockaddr *) &sa,
   1147                                      (socklen_t) sizeof (sa)))
   1148   {
   1149     /* MHD has already closed sv[1] in that case */
   1150     (void) close (sv[0]);
   1151     return -1;
   1152   }
   1153   tc->fd = sv[0];
   1154   stat_connections++;
   1155   /* Our end must never block: the daemon is pumped from this very
   1156      thread, so a blocking write would deadlock the process. */
   1157   fl = fcntl (tc->fd, F_GETFL, 0);
   1158   if (0 <= fl)
   1159     (void) fcntl (tc->fd, F_SETFL, fl | O_NONBLOCK);
   1160   if ( (CLIENT_TLS != cfg.mode) &&
   1161        (CLIENT_TLS_ABANDON != cfg.mode) )
   1162     return 0;
   1163 
   1164   if (GNUTLS_E_SUCCESS !=
   1165       gnutls_certificate_allocate_credentials (&tc->cred))
   1166   {
   1167     tc->cred = NULL;
   1168     tc->dead = 1;
   1169     return 0;
   1170   }
   1171   if (cfg.client_cert)
   1172   {
   1173     gnutls_datum_t c;
   1174     gnutls_datum_t k;
   1175 
   1176     c.data = (unsigned char *) (intptr_t) srv_self_signed_cert_pem;
   1177     c.size = (unsigned int) strlen (srv_self_signed_cert_pem);
   1178     k.data = (unsigned char *) (intptr_t) srv_self_signed_key_pem;
   1179     k.size = (unsigned int) strlen (srv_self_signed_key_pem);
   1180     (void) gnutls_certificate_set_x509_key_mem (tc->cred, &c, &k,
   1181                                                 GNUTLS_X509_FMT_PEM);
   1182   }
   1183   flags = GNUTLS_CLIENT;
   1184 #if GNUTLS_VERSION_MAJOR >= 3
   1185   flags |= GNUTLS_NONBLOCK;
   1186 #endif
   1187 #if GNUTLS_VERSION_NUMBER >= 0x030402
   1188   flags |= GNUTLS_NO_SIGNAL;
   1189 #endif
   1190   if (GNUTLS_E_SUCCESS != gnutls_init (&tc->sess, flags))
   1191   {
   1192     tc->sess = NULL;
   1193     tc->dead = 1;
   1194     return 0;
   1195   }
   1196   if (GNUTLS_E_SUCCESS !=
   1197       gnutls_priority_set_direct (tc->sess,
   1198                                   client_prio_tbl[cfg.client_prio_idx],
   1199                                   NULL))
   1200     (void) gnutls_priority_set_direct (tc->sess, "NORMAL", NULL);
   1201   if (GNUTLS_E_SUCCESS !=
   1202       gnutls_credentials_set (tc->sess, GNUTLS_CRD_CERTIFICATE, tc->cred))
   1203     tc->dead = 1;
   1204   if ( (cfg.client_sni) &&
   1205        (0 != sni_name_len) )
   1206     (void) gnutls_server_name_set (tc->sess,
   1207                                    GNUTLS_NAME_DNS,
   1208                                    sni_name,
   1209                                    sni_name_len);
   1210   gnutls_transport_set_int (tc->sess, tc->fd);
   1211   /* GNUTLS_INDEFINITE_TIMEOUT: the default handshake timeout is a wall
   1212      clock deadline, and this harness must not depend on the clock. */
   1213   gnutls_handshake_set_timeout (tc->sess, 0);
   1214   return 0;
   1215 }
   1216 
   1217 
   1218 static void
   1219 tc_send (struct MHD_Daemon *d,
   1220          struct tls_client *tc,
   1221          const uint8_t *buf,
   1222          size_t len)
   1223 {
   1224   size_t off = 0;
   1225   unsigned int stall = 0;
   1226 
   1227   if ( (0 > tc->fd) ||
   1228        (0 == len) )
   1229     return;
   1230   if (NULL == tc->sess)
   1231   {
   1232     while ( (off < len) &&
   1233             (stall < 64) )
   1234     {
   1235       ssize_t s = send (tc->fd, buf + off, len - off, MSG_DONTWAIT);
   1236 
   1237       if (0 < s)
   1238       {
   1239         off += (size_t) s;
   1240         stall = 0;
   1241         continue;
   1242       }
   1243       stall++;
   1244       pump_and_drain (d, tc, 2);
   1245       if ( (0 > s) &&
   1246            (EAGAIN != errno) &&
   1247            (EWOULDBLOCK != errno) &&
   1248            (EINTR != errno) )
   1249         break;
   1250     }
   1251     return;
   1252   }
   1253   if ( (0 != tc->dead) ||
   1254        (0 == tc->hs_done) )
   1255     return;
   1256   while ( (off < len) &&
   1257           (stall < 64) )
   1258   {
   1259     /* On GNUTLS_E_AGAIN the call has to be repeated with exactly the
   1260        same arguments, which is why @a off is only advanced on success. */
   1261     ssize_t s = gnutls_record_send (tc->sess, buf + off, len - off);
   1262 
   1263     if (0 < s)
   1264     {
   1265       off += (size_t) s;
   1266       stall = 0;
   1267       continue;
   1268     }
   1269     if ( (GNUTLS_E_AGAIN == s) ||
   1270          (GNUTLS_E_INTERRUPTED == s) )
   1271     {
   1272       stall++;
   1273       pump_and_drain (d, tc, 2);
   1274       continue;
   1275     }
   1276     if (0 != gnutls_error_is_fatal ((int) s))
   1277       tc->dead = 1;
   1278     break;
   1279   }
   1280 }
   1281 
   1282 
   1283 /**
   1284  * Tear the client end down.  Every GnuTLS object is released on every
   1285  * path, including the ones where the session never got off the ground.
   1286  */
   1287 static void
   1288 tc_close (struct MHD_Daemon *d,
   1289           struct tls_client *tc)
   1290 {
   1291   if (NULL != tc->sess)
   1292   {
   1293     if ( (cfg.client_bye) &&
   1294          (0 == tc->dead) &&
   1295          (0 != tc->hs_done) )
   1296     {
   1297       unsigned int i;
   1298 
   1299       for (i = 0; i < 8; i++)
   1300       {
   1301         int ret = gnutls_bye (tc->sess, GNUTLS_SHUT_WR);
   1302 
   1303         if ( (GNUTLS_E_AGAIN != ret) &&
   1304              (GNUTLS_E_INTERRUPTED != ret) )
   1305           break;
   1306         run_once (d);
   1307       }
   1308     }
   1309     gnutls_deinit (tc->sess);
   1310     tc->sess = NULL;
   1311   }
   1312   if (NULL != tc->cred)
   1313   {
   1314     gnutls_certificate_free_credentials (tc->cred);
   1315     tc->cred = NULL;
   1316   }
   1317   if (0 <= tc->fd)
   1318   {
   1319     if (cfg.client_shut_wr)
   1320       (void) shutdown (tc->fd, SHUT_WR);
   1321     pump (d, 2);
   1322     (void) close (tc->fd);
   1323     tc->fd = -1;
   1324   }
   1325   tc->hs_done = 0;
   1326   tc->dead = 1;
   1327   pump (d, 4);
   1328 }
   1329 
   1330 
   1331 /**
   1332  * Bring a fresh connection up to the point where payload can be sent.
   1333  */
   1334 static void
   1335 tc_start (struct MHD_Daemon *d,
   1336           struct tls_client *tc)
   1337 {
   1338   if (0 != tc_open (d, tc))
   1339   {
   1340     tc->fd = -1;
   1341     return;
   1342   }
   1343   if (CLIENT_TLS == cfg.mode)
   1344     tc_handshake (d, tc, HANDSHAKE_ROUNDS);
   1345   else if (CLIENT_TLS_ABANDON == cfg.mode)
   1346     tc_handshake (d, tc, cfg.hs_budget);
   1347   else
   1348     pump (d, 1);
   1349 }
   1350 
   1351 
   1352 /* ------------------------------------------------------------------ */
   1353 /* PEM blobs assembled from the input                                  */
   1354 /* ------------------------------------------------------------------ */
   1355 
   1356 /**
   1357  * Build @a out as "-----BEGIN @a label-----\n<body>\n-----END @a
   1358  * label-----\n", with @a body_len bytes of @a body as the payload.  The
   1359  * result is always NUL terminated, because MHD calls strlen() on it.
   1360  */
   1361 static void
   1362 build_fuzz_pem (char *out,
   1363                 size_t out_size,
   1364                 const char *label,
   1365                 const uint8_t *body,
   1366                 size_t body_len)
   1367 {
   1368   size_t o = 0;
   1369   size_t i;
   1370   int n;
   1371 
   1372   n = snprintf (out, out_size, "-----BEGIN %s-----\n", label);
   1373   if ( (0 > n) ||
   1374        ((size_t) n >= out_size) )
   1375   {
   1376     out[0] = '\0';
   1377     return;
   1378   }
   1379   o = (size_t) n;
   1380   if (body_len > FUZZ_PEM_BODY_MAX)
   1381     body_len = FUZZ_PEM_BODY_MAX;
   1382   for (i = 0; (i < body_len) && (o + 32 < out_size); i++)
   1383   {
   1384     /* Keep the blob a C string; a NUL inside would simply truncate it
   1385        for MHD's strlen(), which is a less interesting shape. */
   1386     out[o++] = (char) ((0 == body[i]) ? 'A' : body[i]);
   1387   }
   1388   n = snprintf (out + o, out_size - o, "\n-----END %s-----\n", label);
   1389   if (0 > n)
   1390     out[o] = '\0';
   1391 }
   1392 
   1393 
   1394 /* ------------------------------------------------------------------ */
   1395 /* The fuzz target                                                     */
   1396 /* ------------------------------------------------------------------ */
   1397 
   1398 int
   1399 LLVMFuzzerTestOneInput (const uint8_t *data,
   1400                         size_t size)
   1401 {
   1402   struct MHD_Daemon *d;
   1403   struct MHD_OptionItem opts[12];
   1404   unsigned int nopt = 0;
   1405   unsigned int flags;
   1406   struct tls_client tc;
   1407   size_t pos;
   1408   unsigned int nseg = 0;
   1409   unsigned int nconn = 1;
   1410 
   1411   /* Must happen before the first write() into the socketpair; see
   1412      fuzz_ignore_sigpipe() in fuzz_common.h for why the process dies
   1413      without it.  Idempotent. */
   1414   fuzz_ignore_sigpipe ();
   1415 
   1416   /* The ten configuration bytes are mandatory. */
   1417   if (size < 10)
   1418     return 0;
   1419 
   1420   resp_len = 0;
   1421   memset (&cfg, 0, sizeof (cfg));
   1422 
   1423   {
   1424     const char *nm = sni_name_tbl[(data[9] & 0x07) % SNI_NAME_COUNT];
   1425 
   1426     sni_name_len = strlen (nm);
   1427     memcpy (sni_name, nm, sni_name_len + 1);
   1428   }
   1429 
   1430   cfg.cert = cred_tbl[data[0] % CRED_COUNT].cert;
   1431   cfg.key = cred_tbl[data[0] % CRED_COUNT].key;
   1432 
   1433   cfg.use_trust = (0 != (data[1] & 0x01));
   1434   cfg.use_dhparams = (0 != (data[1] & 0x02));
   1435   cfg.use_sni = (0 != (data[1] & 0x04));
   1436   cfg.use_prio = (0 != (data[1] & 0x08));
   1437   cfg.use_cred_type = (0 != (data[1] & 0x10));
   1438   cfg.no_alpn = (0 != (data[1] & 0x20));
   1439   cfg.key_password = (0 != (data[1] & 0x40));
   1440   cfg.prio_append = (0 != (data[1] & 0x80));
   1441 
   1442   cfg.prio_idx = (unsigned int) (data[2] % PRIO_COUNT);
   1443 
   1444   cfg.cred_type_idx = (unsigned int) (data[3] & 0x07) % CRED_TYPE_COUNT;
   1445   cfg.sni_mode =
   1446     (enum sni_behaviour) (((unsigned int) (data[3] >> 3) & 0x07)
   1447                           % (unsigned int) SNI_BEHAVIOUR_COUNT);
   1448   cfg.trust_garbage = (0 != (data[3] & 0x40));
   1449   cfg.dh_garbage = (0 != (data[3] & 0x80));
   1450 
   1451   cfg.mode = (enum client_mode) (data[4] & 0x03);
   1452   cfg.client_sni = (0 != (data[4] & 0x04));
   1453   cfg.client_cert = (0 != (data[4] & 0x08));
   1454   cfg.client_prio_idx = (unsigned int) ((data[4] >> 4) & 0x03);
   1455   cfg.client_bye = (0 != (data[4] & 0x40));
   1456   cfg.client_shut_wr = (0 != (data[4] & 0x80));
   1457 
   1458   cfg.mem_limit = mem_limit_tbl[(data[5] & 0x0F) % MEM_LIMIT_COUNT];
   1459   cfg.loop_mode = (unsigned int) ((data[5] >> 4) & 0x03);
   1460 
   1461   cfg.resp_kind = (unsigned int) (data[6] & 0x03);
   1462   cfg.conn_info = (0 != (data[6] & 0x04));
   1463   cfg.daemon_info = (0 != (data[6] & 0x08));
   1464   cfg.conn_option = (0 != (data[6] & 0x10));
   1465   cfg.error_reply = (0 != (data[6] & 0x20));
   1466   cfg.resp_header = (0 != (data[6] & 0x40));
   1467   cfg.quiesce = (0 != (data[6] & 0x80));
   1468 
   1469   cfg.hs_budget = 1u + (unsigned int) (data[7] & 0x07);
   1470   cfg.use_tls = (0 == (data[7] & 0x08));
   1471   cfg.allow_upgrade =
   1472     (0 != (data[7] & 0x10)) &&
   1473     (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_UPGRADE));
   1474   cfg.extra_pump = (unsigned int) ((data[7] >> 5) & 0x07);
   1475 
   1476   /* A real handshake is pointless without a working credential setup on
   1477      our own side; fall back to the raw modes if the SNI certificates
   1478      could not be parsed. */
   1479   if ( (cfg.use_sni) &&
   1480        (0 != sni_hosts_init ()) )
   1481     cfg.use_sni = 0;
   1482 
   1483   /* The PEM blobs built from the input.  They are only referenced by
   1484      cred_tbl entries 12-14, but filling them unconditionally keeps this
   1485      out of the option assembly below. */
   1486   {
   1487     size_t body = (size_t) data[8] * 4u;
   1488 
   1489     if (body > size - 10)
   1490       body = size - 10;
   1491     build_fuzz_pem (fuzz_cert_pem, sizeof (fuzz_cert_pem),
   1492                     "CERTIFICATE", data + 10, body);
   1493     build_fuzz_pem (fuzz_key_pem, sizeof (fuzz_key_pem),
   1494                     "PRIVATE KEY", data + 10, body);
   1495   }
   1496 
   1497   if (0 != cfg.mem_limit)
   1498   {
   1499     opts[nopt].option = MHD_OPTION_CONNECTION_MEMORY_LIMIT;
   1500     opts[nopt].value = (intptr_t) cfg.mem_limit;
   1501     opts[nopt].ptr_value = NULL;
   1502     nopt++;
   1503   }
   1504   if (NULL != cfg.key)
   1505   {
   1506     opts[nopt].option = MHD_OPTION_HTTPS_MEM_KEY;
   1507     opts[nopt].value = 0;
   1508     opts[nopt].ptr_value = (void *) (intptr_t) cfg.key;
   1509     nopt++;
   1510   }
   1511   if (NULL != cfg.cert)
   1512   {
   1513     opts[nopt].option = MHD_OPTION_HTTPS_MEM_CERT;
   1514     opts[nopt].value = 0;
   1515     opts[nopt].ptr_value = (void *) (intptr_t) cfg.cert;
   1516     nopt++;
   1517   }
   1518   if (cfg.key_password)
   1519   {
   1520     opts[nopt].option = MHD_OPTION_HTTPS_KEY_PASSWORD;
   1521     opts[nopt].value = 0;
   1522     opts[nopt].ptr_value = (void *) (intptr_t) https_key_password;
   1523     nopt++;
   1524   }
   1525   if (cfg.use_trust)
   1526   {
   1527     opts[nopt].option = MHD_OPTION_HTTPS_MEM_TRUST;
   1528     opts[nopt].value = 0;
   1529     opts[nopt].ptr_value = (void *) (intptr_t)
   1530                            (cfg.trust_garbage ? garbage_cert_pem
   1531                             : ca_cert_pem);
   1532     nopt++;
   1533   }
   1534   if (cfg.use_dhparams)
   1535   {
   1536     opts[nopt].option = MHD_OPTION_HTTPS_MEM_DHPARAMS;
   1537     opts[nopt].value = 0;
   1538     opts[nopt].ptr_value = (void *) (intptr_t)
   1539                            (cfg.dh_garbage ? garbage_dh_pem : dh_params_pem);
   1540     nopt++;
   1541   }
   1542   if (cfg.use_prio)
   1543   {
   1544     opts[nopt].option = cfg.prio_append
   1545                         ? MHD_OPTION_HTTPS_PRIORITIES_APPEND
   1546                         : MHD_OPTION_HTTPS_PRIORITIES;
   1547     opts[nopt].value = 0;
   1548     opts[nopt].ptr_value = (void *) (intptr_t) prio_tbl[cfg.prio_idx];
   1549     nopt++;
   1550   }
   1551   if (cfg.use_cred_type)
   1552   {
   1553     opts[nopt].option = MHD_OPTION_HTTPS_CRED_TYPE;
   1554     opts[nopt].value = (intptr_t) cred_type_tbl[cfg.cred_type_idx];
   1555     opts[nopt].ptr_value = NULL;
   1556     nopt++;
   1557   }
   1558   if (cfg.no_alpn)
   1559   {
   1560     opts[nopt].option = MHD_OPTION_TLS_NO_ALPN;
   1561     opts[nopt].value = 1;
   1562     opts[nopt].ptr_value = NULL;
   1563     nopt++;
   1564   }
   1565   opts[nopt].option = MHD_OPTION_END;
   1566   opts[nopt].value = 0;
   1567   opts[nopt].ptr_value = NULL;
   1568 
   1569   flags = MHD_USE_NO_LISTEN_SOCKET;
   1570   if (cfg.use_tls)
   1571     flags |= MHD_USE_TLS;
   1572   if (fuzz_verbose)
   1573     flags |= MHD_USE_ERROR_LOG;
   1574   if (cfg.allow_upgrade)
   1575     flags |= MHD_ALLOW_UPGRADE;
   1576 
   1577   MHD_set_panic_func (&panic_cb, NULL);
   1578   d = MHD_start_daemon (flags,
   1579                         0,
   1580                         NULL, NULL,
   1581                         &ahc, NULL,
   1582                         MHD_OPTION_ARRAY, opts,
   1583                         /* Passed through the varargs rather than through
   1584                            the option array: the array's ptr_value is a
   1585                            void *, and a function pointer does not
   1586                            portably fit in one.  A NULL here is exactly
   1587                            equivalent to not passing the option. */
   1588                         MHD_OPTION_HTTPS_CERT_CALLBACK,
   1589                         cfg.use_sni ? &sni_callback : NULL,
   1590                         MHD_OPTION_END);
   1591   if (NULL == d)
   1592   {
   1593     stat_daemons_failed++;
   1594     return 0;
   1595   }
   1596   stat_daemons++;
   1597   if (! stats_registered)
   1598   {
   1599     stats_registered = 1;
   1600     (void) atexit (&print_stats);
   1601   }
   1602   if (cfg.daemon_info)
   1603   {
   1604     (void) MHD_get_daemon_info (d, MHD_DAEMON_INFO_LISTEN_FD);
   1605     (void) MHD_get_daemon_info (d, MHD_DAEMON_INFO_FLAGS);
   1606     (void) MHD_get_daemon_info (d, MHD_DAEMON_INFO_CURRENT_CONNECTIONS);
   1607     (void) MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
   1608   }
   1609 
   1610   /* The connection is opened lazily, when the first segment that carries
   1611      wire data is reached, so that a leading op 1 segment can still
   1612      override the server name byte 9 selected. */
   1613   tc.sess = NULL;
   1614   tc.cred = NULL;
   1615   tc.fd = -1;
   1616   tc.hs_done = 0;
   1617   tc.dead = 1;
   1618 
   1619   pos = 10u;
   1620   while ( (pos + 2 <= size) &&
   1621           (nseg < MAX_SEGMENTS) )
   1622   {
   1623     unsigned int hdr = (unsigned int) data[pos]
   1624                        | ((unsigned int) data[pos + 1] << 8);
   1625     unsigned int op = hdr >> 14;
   1626     size_t slen = (size_t) (hdr & 0x3FFF);
   1627 
   1628     pos += 2;
   1629     nseg++;
   1630     if (slen > size - pos)
   1631       slen = size - pos;
   1632 
   1633     if (1 == op)
   1634     {
   1635       /* Server name declaration for the next connection, not wire data. */
   1636       size_t n = slen;
   1637 
   1638       if (n > MAX_SNI_LEN)
   1639         n = MAX_SNI_LEN;
   1640       memcpy (sni_name, data + pos, n);
   1641       /* GnuTLS wants a plain host name, and an embedded NUL would only
   1642          shorten it behind our back. */
   1643       while ( (0 != n) &&
   1644               ('\0' == sni_name[n - 1]) )
   1645         n--;
   1646       sni_name[n] = '\0';
   1647       sni_name_len = n;
   1648       pos += slen;
   1649       continue;
   1650     }
   1651     if (0 > tc.fd)
   1652     {
   1653       tc_start (d, &tc);
   1654       if (0 > tc.fd)
   1655         break;
   1656     }
   1657     else if ( (3 == op) &&
   1658               (nconn < MAX_CONNECTIONS) )
   1659     {
   1660       tc_close (d, &tc);
   1661       tc_start (d, &tc);
   1662       nconn++;
   1663       if (0 > tc.fd)
   1664         break;
   1665     }
   1666     if (0 != slen)
   1667       tc_send (d, &tc, data + pos, slen);
   1668     pos += slen;
   1669     pump_and_drain (d, &tc, (2 == op) ? (6u + cfg.extra_pump) : 3u);
   1670   }
   1671   if (0 > tc.fd)
   1672     tc_start (d, &tc);
   1673   pump_and_drain (d, &tc, 2u + cfg.extra_pump);
   1674   tc_close (d, &tc);
   1675 
   1676   if (cfg.quiesce)
   1677     (void) MHD_quiesce_daemon (d);
   1678   MHD_stop_daemon (d);
   1679   return 0;
   1680 }
   1681 
   1682 
   1683 /* ------------------------------------------------------------------ */
   1684 /* Structure-aware generator                                           */
   1685 /* ------------------------------------------------------------------ */
   1686 
   1687 struct sbuf
   1688 {
   1689   uint8_t *p;
   1690   size_t len;
   1691   size_t cap;
   1692 };
   1693 
   1694 
   1695 static void
   1696 sb_raw (struct sbuf *b,
   1697         const void *v,
   1698         size_t n)
   1699 {
   1700   if (b->len + n > b->cap)
   1701     n = b->cap - b->len;
   1702   memcpy (b->p + b->len, v, n);
   1703   b->len += n;
   1704 }
   1705 
   1706 
   1707 static void
   1708 sb_str (struct sbuf *b,
   1709         const char *s)
   1710 {
   1711   sb_raw (b, s, strlen (s));
   1712 }
   1713 
   1714 
   1715 static void
   1716 sb_u32 (struct sbuf *b,
   1717         uint32_t v)
   1718 {
   1719   char tmp[16];
   1720   unsigned int n = 0;
   1721 
   1722   do
   1723   {
   1724     tmp[n++] = (char) ('0' + (v % 10u));
   1725     v /= 10u;
   1726   }
   1727   while ( (0 != v) &&
   1728           (n < sizeof (tmp)) );
   1729   while (0 != n)
   1730   {
   1731     char c = tmp[--n];
   1732 
   1733     sb_raw (b, &c, 1);
   1734   }
   1735 }
   1736 
   1737 
   1738 enum gen_shape
   1739 {
   1740   SHAPE_TLS_HTTP = 0,   /**< good credentials, real handshake, HTTP over TLS */
   1741   SHAPE_RAW_BYTES,      /**< good credentials, junk at the TLS socket */
   1742   SHAPE_ABANDON,        /**< a real client that walks away mid-handshake */
   1743   SHAPE_BAD_CREDS,      /**< mismatched/garbage/absent key or certificate */
   1744   SHAPE_BAD_OPTIONS,    /**< bogus priorities, credential types, no MHD_USE_TLS */
   1745   SHAPE_SNI,            /**< the certificate callback, all behaviours */
   1746   SHAPE_PEM_FUZZ,       /**< PEM blobs built from the generator's own bytes */
   1747   SHAPE_RECORDS,        /**< hand-built TLS records */
   1748   SHAPE_COUNT
   1749 };
   1750 
   1751 static int forced_shape = -1;
   1752 static int forced_shape_read;
   1753 
   1754 static const char *const gen_methods[] = {
   1755   "GET", "POST", "HEAD", "PUT", "OPTIONS", "BREW"
   1756 };
   1757 
   1758 static const char *const gen_targets[] = {
   1759   "/", "/a", "/index.html", "/a?b=c", "/%41%42", "*", "//"
   1760 };
   1761 
   1762 static const char *const gen_versions[] = {
   1763   "HTTP/1.1", "HTTP/1.0", "HTTP/1.2", "HTTP/9.9"
   1764 };
   1765 
   1766 static const char *const gen_hdr_names[] = {
   1767   "Host", "User-Agent", "Accept", "Connection", "X-Fuzz", "Cookie",
   1768   "Content-Type", "Expect"
   1769 };
   1770 
   1771 static const char *const gen_hdr_values[] = {
   1772   "x", "localhost", "*/*", "keep-alive", "close", "100-continue",
   1773   "text/plain", "a=b"
   1774 };
   1775 
   1776 
   1777 /**
   1778  * A plain HTTP request; over TLS this is what makes MHD leave the
   1779  * handshake state machine and enter the ordinary parser.
   1780  */
   1781 static void
   1782 gen_http_request (struct fuzz_rng *rng,
   1783                   struct sbuf *b)
   1784 {
   1785   unsigned int nh;
   1786   unsigned int i;
   1787   int with_body;
   1788 
   1789   sb_str (b, gen_methods[fuzz_below (rng, (uint32_t)
   1790                                      (sizeof (gen_methods)
   1791                                       / sizeof (gen_methods[0])))]);
   1792   sb_str (b, " ");
   1793   sb_str (b, gen_targets[fuzz_below (rng, (uint32_t)
   1794                                      (sizeof (gen_targets)
   1795                                       / sizeof (gen_targets[0])))]);
   1796   sb_str (b, " ");
   1797   sb_str (b, gen_versions[fuzz_below (rng, (uint32_t)
   1798                                       (sizeof (gen_versions)
   1799                                        / sizeof (gen_versions[0])))]);
   1800   sb_str (b, "\r\n");
   1801   with_body = fuzz_chance (rng, 3);
   1802   nh = fuzz_below (rng, 4);
   1803   for (i = 0; i < nh; i++)
   1804   {
   1805     sb_str (b, gen_hdr_names[fuzz_below (rng, (uint32_t)
   1806                                          (sizeof (gen_hdr_names)
   1807                                           / sizeof (gen_hdr_names[0])))]);
   1808     sb_str (b, ": ");
   1809     sb_str (b, gen_hdr_values[fuzz_below (rng, (uint32_t)
   1810                                           (sizeof (gen_hdr_values)
   1811                                            / sizeof (gen_hdr_values[0])))]);
   1812     sb_str (b, "\r\n");
   1813   }
   1814   if (with_body)
   1815   {
   1816     unsigned int blen = fuzz_below (rng, 64);
   1817 
   1818     sb_str (b, "Content-Length: ");
   1819     sb_u32 (b, blen);
   1820     sb_str (b, "\r\n\r\n");
   1821     for (i = 0; i < blen; i++)
   1822     {
   1823       char c = (char) ('a' + (int) fuzz_below (rng, 26));
   1824 
   1825       sb_raw (b, &c, 1);
   1826     }
   1827     return;
   1828   }
   1829   sb_str (b, "\r\n");
   1830 }
   1831 
   1832 
   1833 /**
   1834  * Something that looks like a TLS record: a content type, a version, a
   1835  * length and a payload.  Most of this lands in GnuTLS's record parser
   1836  * rather than in MHD, which is why the generator spends only one shape
   1837  * on it.
   1838  */
   1839 static void
   1840 gen_tls_records (struct fuzz_rng *rng,
   1841                  struct sbuf *b)
   1842 {
   1843   unsigned int n = 1 + fuzz_below (rng, 4);
   1844   unsigned int i;
   1845   unsigned int j;
   1846 
   1847   for (i = 0; i < n; i++)
   1848   {
   1849     uint8_t hdr[5];
   1850     unsigned int plen = fuzz_below (rng, 96);
   1851     unsigned int declared = fuzz_chance (rng, 3)
   1852                             ? fuzz_below (rng, 0x4000)
   1853                             : plen;
   1854 
   1855     hdr[0] = fuzz_chance (rng, 4)
   1856              ? fuzz_byte (rng)
   1857              : (uint8_t) (20 + fuzz_below (rng, 4));
   1858     hdr[1] = 0x03;
   1859     hdr[2] = (uint8_t) fuzz_below (rng, 5);
   1860     hdr[3] = (uint8_t) ((declared >> 8) & 0xFF);
   1861     hdr[4] = (uint8_t) (declared & 0xFF);
   1862     sb_raw (b, hdr, sizeof (hdr));
   1863     for (j = 0; j < plen; j++)
   1864     {
   1865       uint8_t v = fuzz_byte (rng);
   1866 
   1867       sb_raw (b, &v, 1);
   1868     }
   1869   }
   1870 }
   1871 
   1872 
   1873 /**
   1874  * Number of leading entries of #prio_tbl that GnuTLS accepts.  Beyond
   1875  * that the daemon refuses to start, which is a fine thing to fuzz but a
   1876  * poor way to reach the handshake.
   1877  */
   1878 #define PRIO_VALID_COUNT 7
   1879 
   1880 
   1881 /**
   1882  * Constrain the configuration bytes so that MHD_start_daemon() actually
   1883  * succeeds.  Used by the shapes whose point is what happens *after* the
   1884  * daemon is up; the option surface itself is fuzzed by the shapes that
   1885  * do not call this.
   1886  */
   1887 static void
   1888 make_daemon_startable (struct fuzz_rng *rng,
   1889                        uint8_t *cfg_bytes)
   1890 {
   1891   cfg_bytes[1] &= (uint8_t) ~0x10u;      /* no credential type override */
   1892   cfg_bytes[3] &= (uint8_t) ~0xC0u;      /* valid trust store, valid DH */
   1893   if (0 != (cfg_bytes[1] & 0x08u))
   1894     cfg_bytes[2] = (uint8_t) fuzz_below (rng, PRIO_VALID_COUNT);
   1895   cfg_bytes[7] &= (uint8_t) ~0x08u;      /* keep MHD_USE_TLS */
   1896 }
   1897 
   1898 
   1899 /**
   1900  * Emit one segment with the given op code.
   1901  */
   1902 static void
   1903 emit_segment (struct sbuf *out,
   1904               unsigned int op,
   1905               const uint8_t *payload,
   1906               size_t len)
   1907 {
   1908   unsigned int hv;
   1909   uint8_t hdr[2];
   1910 
   1911   if (len > 0x3FFF)
   1912     len = 0x3FFF;
   1913   hv = (op << 14) | (unsigned int) len;
   1914   hdr[0] = (uint8_t) (hv & 0xFF);
   1915   hdr[1] = (uint8_t) (hv >> 8);
   1916   sb_raw (out, hdr, 2);
   1917   sb_raw (out, payload, len);
   1918 }
   1919 
   1920 
   1921 static size_t
   1922 fuzz_generate (struct fuzz_rng *rng,
   1923                uint8_t *buf,
   1924                size_t cap)
   1925 {
   1926   struct sbuf out;
   1927   struct sbuf rb;
   1928   uint8_t req[GEN_BUF_SIZE];
   1929   uint8_t cfg_bytes[10];
   1930   enum gen_shape shape;
   1931   unsigned int nreq;
   1932   unsigned int i;
   1933 
   1934   out.p = buf;
   1935   out.len = 0;
   1936   out.cap = cap;
   1937 
   1938   if (! forced_shape_read)
   1939   {
   1940     const char *e = getenv ("MHD_FUZZ_SHAPE");
   1941 
   1942     forced_shape_read = 1;
   1943     if (NULL != e)
   1944       forced_shape = atoi (e);
   1945   }
   1946   if (0 <= forced_shape)
   1947     shape = (enum gen_shape) (forced_shape % (int) SHAPE_COUNT);
   1948   else
   1949     shape = (enum gen_shape) fuzz_below (rng, (uint32_t) SHAPE_COUNT);
   1950 
   1951   for (i = 0; i < sizeof (cfg_bytes); i++)
   1952     cfg_bytes[i] = fuzz_byte (rng);
   1953 
   1954   /* Byte 0 picks the credentials, byte 4 (bits 0-1) the client, and byte
   1955      1 which options are passed at all; every shape below narrows exactly
   1956      those and leaves the rest of the configuration space random. */
   1957   cfg_bytes[7] &= (uint8_t) ~0x08u;      /* keep MHD_USE_TLS by default */
   1958   switch (shape)
   1959   {
   1960   case SHAPE_TLS_HTTP:
   1961     cfg_bytes[0] = (uint8_t) (fuzz_chance (rng, 2) ? 0 : 1);
   1962     cfg_bytes[4] = (uint8_t) ((cfg_bytes[4] & ~0x03u) | CLIENT_TLS);
   1963     cfg_bytes[1] &= (uint8_t) ~0x04u;    /* no SNI callback */
   1964     make_daemon_startable (rng, cfg_bytes);
   1965     break;
   1966   case SHAPE_RAW_BYTES:
   1967     cfg_bytes[0] = 0;
   1968     cfg_bytes[4] = (uint8_t) ((cfg_bytes[4] & ~0x03u) | CLIENT_RAW);
   1969     make_daemon_startable (rng, cfg_bytes);
   1970     break;
   1971   case SHAPE_ABANDON:
   1972     cfg_bytes[0] = (uint8_t) (fuzz_chance (rng, 2) ? 0 : 1);
   1973     cfg_bytes[4] = (uint8_t) ((cfg_bytes[4] & ~0x03u) | CLIENT_TLS_ABANDON);
   1974     cfg_bytes[7] = (uint8_t) ((cfg_bytes[7] & ~0x07u)
   1975                               + fuzz_below (rng, 6));
   1976     make_daemon_startable (rng, cfg_bytes);
   1977     break;
   1978   case SHAPE_BAD_CREDS:
   1979     /* entries 2-11 of cred_tbl are the broken ones */
   1980     cfg_bytes[0] = (uint8_t) (2 + fuzz_below (rng, 10));
   1981     cfg_bytes[4] = (uint8_t) ((cfg_bytes[4] & ~0x03u)
   1982                               | (fuzz_chance (rng, 2) ? CLIENT_TLS
   1983                                  : CLIENT_RAW));
   1984     break;
   1985   case SHAPE_BAD_OPTIONS:
   1986     cfg_bytes[1] |= 0x18u;               /* priorities + credential type */
   1987     cfg_bytes[2] = (uint8_t) fuzz_below (rng, (uint32_t) PRIO_COUNT);
   1988     cfg_bytes[3] = fuzz_byte (rng);
   1989     if (fuzz_chance (rng, 4))
   1990       cfg_bytes[7] |= 0x08u;             /* HTTPS options, but no MHD_USE_TLS */
   1991     cfg_bytes[4] = (uint8_t) ((cfg_bytes[4] & ~0x03u)
   1992                               | (fuzz_chance (rng, 2) ? CLIENT_TLS
   1993                                  : CLIENT_RAW));
   1994     break;
   1995   case SHAPE_SNI:
   1996     cfg_bytes[0] = (uint8_t) (fuzz_chance (rng, 3) ? 6 : 0);
   1997     cfg_bytes[3] = (uint8_t)
   1998                    ((cfg_bytes[3] & ~0x38u)
   1999                     | (fuzz_below (rng, (uint32_t) SNI_BEHAVIOUR_COUNT) << 3));
   2000     cfg_bytes[4] = (uint8_t) ((cfg_bytes[4] & ~0x03u) | CLIENT_TLS | 0x04u);
   2001     cfg_bytes[9] = (uint8_t) fuzz_below (rng, (uint32_t) SNI_NAME_COUNT);
   2002     make_daemon_startable (rng, cfg_bytes);
   2003     cfg_bytes[1] |= 0x04u;               /* the certificate callback */
   2004     break;
   2005   case SHAPE_PEM_FUZZ:
   2006     cfg_bytes[0] = (uint8_t) (12 + fuzz_below (rng, 3));
   2007     cfg_bytes[8] = (uint8_t) (1 + fuzz_below (rng, 64));
   2008     cfg_bytes[4] = (uint8_t) ((cfg_bytes[4] & ~0x03u)
   2009                               | (fuzz_chance (rng, 2) ? CLIENT_TLS
   2010                                  : CLIENT_RAW));
   2011     break;
   2012   case SHAPE_RECORDS:
   2013     cfg_bytes[0] = 0;
   2014     cfg_bytes[4] = (uint8_t) ((cfg_bytes[4] & ~0x03u) | CLIENT_RECORDS);
   2015     make_daemon_startable (rng, cfg_bytes);
   2016     break;
   2017   case SHAPE_COUNT:
   2018   default:
   2019     break;
   2020   }
   2021   /* Byte 9 already carries a server name; now and then hand the same
   2022      one over as an op 1 segment instead, so that the segment form is
   2023      exercised too.  Generated inputs are never written to corpus/, so
   2024      unlike the seeds they may use op 1 (see the note at the top). */
   2025   sb_raw (&out, cfg_bytes, sizeof (cfg_bytes));
   2026   if (fuzz_chance (rng, 4))
   2027   {
   2028     const char *nm = sni_name_tbl[cfg_bytes[9] & 0x07];
   2029 
   2030     emit_segment (&out, 1u, (const uint8_t *) nm, strlen (nm));
   2031   }
   2032 
   2033   nreq = 1u + (fuzz_chance (rng, 4) ? 1u : 0u);
   2034   for (i = 0; i < nreq; i++)
   2035   {
   2036     unsigned int op;
   2037 
   2038     rb.p = req;
   2039     rb.len = 0;
   2040     rb.cap = sizeof (req);
   2041     switch (shape)
   2042     {
   2043     case SHAPE_RECORDS:
   2044       gen_tls_records (rng, &rb);
   2045       break;
   2046     case SHAPE_RAW_BYTES:
   2047       {
   2048         unsigned int n = 1 + fuzz_below (rng, 256);
   2049         unsigned int j;
   2050 
   2051         for (j = 0; j < n; j++)
   2052         {
   2053           uint8_t v = fuzz_byte (rng);
   2054 
   2055           sb_raw (&rb, &v, 1);
   2056         }
   2057         break;
   2058       }
   2059     default:
   2060       gen_http_request (rng, &rb);
   2061       break;
   2062     }
   2063     if (0 != i)
   2064       op = 3u;                           /* a fresh connection */
   2065     else
   2066       op = fuzz_chance (rng, 3) ? 2u : 0u;
   2067     /* Split the payload now and then: MHD's parser is incremental and
   2068        the TLS record boundaries move with the split. */
   2069     if ( (rb.len > 8) &&
   2070          fuzz_chance (rng, 3) )
   2071     {
   2072       size_t cut = 1 + fuzz_below (rng, (uint32_t) (rb.len - 1));
   2073 
   2074       emit_segment (&out, op, req, cut);
   2075       emit_segment (&out, 2u, req + cut, rb.len - cut);
   2076     }
   2077     else
   2078     {
   2079       emit_segment (&out, op, req, rb.len);
   2080     }
   2081   }
   2082   return out.len;
   2083 }
   2084 
   2085 
   2086 /* ------------------------------------------------------------------ */
   2087 /* Built-in seed corpus                                                */
   2088 /* ------------------------------------------------------------------ */
   2089 
   2090 struct seed_part
   2091 {
   2092   unsigned int op;              /**< 0 send, 1 server name, 2 send+pump, 3 new */
   2093   const char *txt;              /**< NUL terminated payload */
   2094 };
   2095 
   2096 struct seed_def
   2097 {
   2098   const char *name;
   2099   unsigned char cfg[10];
   2100   struct seed_part parts[4];
   2101 };
   2102 
   2103 #define P_END { 0, NULL }
   2104 
   2105 /* The configuration bytes are written out in full so that a seed can be
   2106    read without decoding: see the input format at the top of this file. */
   2107 static const struct seed_def seeds[] = {
   2108   /* A complete TLS 1.3 handshake followed by an ordinary request: the
   2109      only shape that reaches the handshake -> HTTP parser transition. */
   2110   { "tls-handshake-get",
   2111     { 0, 0x00, 0, 0, 0x41, 0x00, 0x04, 0x00, 0, 0 },
   2112     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END } },
   2113 
   2114   /* The same, but the request arrives in two TLS records. */
   2115   { "tls-handshake-split",
   2116     { 0, 0x00, 0, 0, 0x41, 0x00, 0x04, 0x00, 0, 0 },
   2117     { { 0, "GET / HTTP/1.1\r\nHo" },
   2118       { 2, "st: x\r\n\r\n" }, P_END, P_END } },
   2119 
   2120   /* Keep-alive over TLS: two requests on one session, then gnutls_bye(). */
   2121   { "tls-keepalive",
   2122     { 0, 0x00, 0, 0, 0x41, 0x00, 0x00, 0x00, 0, 0 },
   2123     { { 0, "GET /a HTTP/1.1\r\nHost: x\r\n\r\n" },
   2124       { 2, "GET /b HTTP/1.1\r\nHost: x\r\nConnection: close\r\n\r\n" },
   2125       P_END, P_END } },
   2126 
   2127   /* A second connection, i.e. a second handshake on the same daemon. */
   2128   { "tls-second-connection",
   2129     { 0, 0x00, 0, 0, 0x41, 0x00, 0x00, 0x00, 0, 0 },
   2130     { { 0, "GET /a HTTP/1.1\r\nHost: x\r\n\r\n" },
   2131       { 3, "GET /b HTTP/1.1\r\nHost: x\r\n\r\n" },
   2132       P_END, P_END } },
   2133 
   2134   /* Plain HTTP at a TLS port: the record layer sees "GET ..." and the
   2135      handshake fails, which is MHD_run_tls_handshake_()'s error arm. */
   2136   { "plain-http-at-tls-port",
   2137     { 0, 0x00, 0, 0, 0x00, 0x00, 0x00, 0x00, 0, 0 },
   2138     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END } },
   2139 
   2140   /* Nothing at all, then EOF: the connection dies in MHD_TLS_CONN_INIT. */
   2141   { "eof-in-init",
   2142     { 0, 0x00, 0, 0, 0x80, 0x00, 0x00, 0x00, 0, 0 },
   2143     { { 0, "" }, P_END, P_END, P_END } },
   2144 
   2145   /* A real client that walks away after a single handshake round: MHD is
   2146      left in MHD_TLS_CONN_HANDSHAKING when the socket closes. */
   2147   { "abandon-handshake",
   2148     { 0, 0x00, 0, 0, 0x02, 0x00, 0x00, 0x00, 0, 0 },
   2149     { { 0, "" }, P_END, P_END, P_END } },
   2150 
   2151   /* Certificate and key do not belong together. */
   2152   { "mismatched-key",
   2153     { 2, 0x00, 0, 0, 0x01, 0x00, 0x00, 0x00, 0, 0 },
   2154     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END } },
   2155 
   2156   /* No certificate at all: MHD_start_daemon() has to fail cleanly. */
   2157   { "no-certificate",
   2158     { 6, 0x00, 0, 0, 0x01, 0x00, 0x00, 0x00, 0, 0 },
   2159     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END } },
   2160 
   2161   /* PEM armour with a payload that is not base64. */
   2162   { "garbage-pem",
   2163     { 10, 0x00, 0, 0, 0x01, 0x00, 0x00, 0x00, 0, 0 },
   2164     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END } },
   2165 
   2166   /* A priority string GnuTLS rejects (index 9 of prio_tbl). */
   2167   { "bogus-priorities",
   2168     { 0, 0x08, 9, 0, 0x01, 0x00, 0x00, 0x00, 0, 0 },
   2169     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END } },
   2170 
   2171   /* The same string through MHD_OPTION_HTTPS_PRIORITIES_APPEND. */
   2172   { "bogus-priorities-append",
   2173     { 0, 0x88, 10, 0, 0x01, 0x00, 0x00, 0x00, 0, 0 },
   2174     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END } },
   2175 
   2176   /* TLS 1.2 only on both ends, with the trust store and a client
   2177      certificate request. */
   2178   { "tls12-with-trust",
   2179     { 0, 0x01, 2, 0, 0x29, 0x00, 0x04, 0x00, 0, 0 },
   2180     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END } },
   2181 
   2182   /* Valid Diffie-Hellman parameters (RFC 3526 group 14). */
   2183   { "valid-dhparams",
   2184     { 0, 0x02, 0, 0, 0x21, 0x00, 0x00, 0x00, 0, 0 },
   2185     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END } },
   2186 
   2187   /* Malformed Diffie-Hellman parameters: MHD_start_daemon() must fail. */
   2188   { "garbage-dhparams",
   2189     { 0, 0x02, 0, 0x80, 0x01, 0x00, 0x00, 0x00, 0, 0 },
   2190     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END } },
   2191 
   2192   /* A credential type MHD does not support (GNUTLS_CRD_ANON). */
   2193   { "cred-type-anon",
   2194     { 0, 0x10, 0, 0x02, 0x01, 0x00, 0x00, 0x00, 0, 0 },
   2195     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END } },
   2196 
   2197   /* GNUTLS_CRD_PSK without a PSK callback: the daemon starts, the
   2198      handshake cannot. */
   2199   { "cred-type-psk",
   2200     { 0, 0x10, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0, 0 },
   2201     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END } },
   2202 
   2203   /* The SNI callback, answering for the presented name (byte 9 = 0,
   2204      "test-mhdserver").  No op 1 segment here or below: see the note on
   2205      the shared corpus at the top of this file. */
   2206   { "sni-by-name",
   2207     { 6, 0x04, 0, 0x18, 0x05, 0x00, 0x04, 0x00, 0, 0 },
   2208     { { 0, "GET / HTTP/1.1\r\nHost: test-mhdserver\r\n\r\n" },
   2209       P_END, P_END, P_END } },
   2210 
   2211   /* The SNI callback failing outright. */
   2212   { "sni-callback-fails",
   2213     { 6, 0x04, 0, 0x08, 0x05, 0x00, 0x00, 0x00, 0, 0 },
   2214     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" },
   2215       P_END, P_END, P_END } },
   2216 
   2217   /* The SNI callback answering with an empty certificate list. */
   2218   { "sni-callback-empty",
   2219     { 6, 0x04, 0, 0x10, 0x05, 0x00, 0x00, 0x00, 0, 0 },
   2220     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" },
   2221       P_END, P_END, P_END } },
   2222 
   2223   /* The SNI callback answering with a key that is not the certificate's
   2224      (byte 9 = 1, "localhost"). */
   2225   { "sni-callback-mismatch",
   2226     { 6, 0x04, 0, 0x20, 0x05, 0x00, 0x00, 0x00, 0, 1 },
   2227     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" },
   2228       P_END, P_END, P_END } },
   2229 
   2230   /* The SNI callback answering with a certificate but no key. */
   2231   { "sni-callback-no-key",
   2232     { 6, 0x04, 0, 0x28, 0x05, 0x00, 0x00, 0x00, 0, 0 },
   2233     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" },
   2234       P_END, P_END, P_END } },
   2235 
   2236   /* An unknown server name with the by-name callback (byte 9 = 3,
   2237      "nobody.example.org"): no certificate. */
   2238   { "sni-unknown-name",
   2239     { 6, 0x04, 0, 0x18, 0x05, 0x00, 0x00, 0x00, 0, 3 },
   2240     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" },
   2241       P_END, P_END, P_END } },
   2242 
   2243   /* A PEM blob assembled from the payload below (cred_tbl entry 14). */
   2244   { "fuzzed-pem",
   2245     { 14, 0x00, 0, 0, 0x01, 0x00, 0x00, 0x00, 32, 0 },
   2246     { { 0, "MIIFSzCCAzOgAwIBAgIBBDANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCUlUx" },
   2247       P_END, P_END, P_END } },
   2248 
   2249   /* A truncated TLS record header, then EOF. */
   2250   { "short-record",
   2251     { 0, 0x00, 0, 0, 0x00, 0x00, 0x00, 0x00, 0, 0 },
   2252     { { 0, "\x16\x03\x01" }, P_END, P_END, P_END } },
   2253 
   2254   /* A record that promises far more data than it delivers. */
   2255   { "record-length-lie",
   2256     { 0, 0x00, 0, 0, 0x00, 0x00, 0x00, 0x00, 0, 0 },
   2257     { { 0, "\x16\x03\x01\x3f\xff\x01\x02\x03\x04" }, P_END, P_END, P_END } },
   2258 
   2259   /* The HTTPS options on a daemon started without MHD_USE_TLS. */
   2260   { "no-use-tls-flag",
   2261     { 0, 0x0F, 0, 0, 0x00, 0x00, 0x00, 0x08, 0, 0 },
   2262     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END } },
   2263 
   2264   /* A tiny connection memory pool with a real TLS session. */
   2265   { "small-pool-tls",
   2266     { 0, 0x00, 0, 0, 0x41, 0x01, 0x00, 0x00, 0, 0 },
   2267     { { 0, "GET /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa HTTP/1.1\r\n"
   2268         "Host: x\r\nX-Long: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\n\r\n" },
   2269       P_END, P_END, P_END } },
   2270 
   2271   /* A request body over TLS, so that the receive adapter is used for
   2272      more than the request line. */
   2273   { "tls-request-body",
   2274     { 0, 0x00, 0, 0, 0x41, 0x00, 0x00, 0x00, 0, 0 },
   2275     { { 0, "POST /a HTTP/1.1\r\nHost: x\r\nContent-Length: 11\r\n\r\n"
   2276         "hello world" },
   2277       P_END, P_END, P_END } },
   2278 
   2279   /* The external event loop (MHD_get_fdset() + MHD_run_from_select()). */
   2280   { "tls-external-loop",
   2281     { 0, 0x00, 0, 0, 0x41, 0x10, 0x04, 0x00, 0, 0 },
   2282     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END } },
   2283 
   2284   /* MHD_quiesce_daemon() with a live TLS connection. */
   2285   { "tls-quiesce",
   2286     { 0, 0x00, 0, 0, 0x41, 0x00, 0x80, 0x00, 0, 0 },
   2287     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END } }
   2288 };
   2289 
   2290 static uint8_t seed_render_buf[2048];
   2291 
   2292 
   2293 static size_t
   2294 fuzz_seed_count (void)
   2295 {
   2296   return sizeof (seeds) / sizeof (seeds[0]);
   2297 }
   2298 
   2299 
   2300 static const uint8_t *
   2301 fuzz_seed_get (size_t idx,
   2302                size_t *len)
   2303 {
   2304   const struct seed_def *sd = &seeds[idx];
   2305   struct sbuf b;
   2306   unsigned int i;
   2307 
   2308   b.p = seed_render_buf;
   2309   b.len = 0;
   2310   b.cap = sizeof (seed_render_buf);
   2311   sb_raw (&b, sd->cfg, sizeof (sd->cfg));
   2312   for (i = 0; i < sizeof (sd->parts) / sizeof (sd->parts[0]); i++)
   2313   {
   2314     if (NULL == sd->parts[i].txt)
   2315       break;
   2316     emit_segment (&b, sd->parts[i].op,
   2317                   (const uint8_t *) sd->parts[i].txt,
   2318                   strlen (sd->parts[i].txt));
   2319   }
   2320   *len = b.len;
   2321   return seed_render_buf;
   2322 }
   2323 
   2324 
   2325 #else  /* ! HTTPS_SUPPORT */
   2326 
   2327 /*
   2328  * MHD was configured without HTTPS (which is what
   2329  * contrib/oss-fuzz/build.sh does for the MemorySanitizer build), so
   2330  * there is no TLS layer to fuzz.  The file still has to produce a valid
   2331  * fuzz target: LLVMFuzzerTestOneInput() must exist unconditionally, or
   2332  * an OSS-Fuzz build of this harness would silently be an empty binary.
   2333  */
   2334 
   2335 int
   2336 LLVMFuzzerTestOneInput (const uint8_t *data,
   2337                         size_t size)
   2338 {
   2339   fuzz_ignore_sigpipe ();
   2340   (void) data;
   2341   (void) size;
   2342   return 0;
   2343 }
   2344 
   2345 
   2346 static size_t
   2347 fuzz_generate (struct fuzz_rng *rng,
   2348                uint8_t *buf,
   2349                size_t cap)
   2350 {
   2351   (void) rng;
   2352   if (0 == cap)
   2353     return 0;
   2354   buf[0] = 0;
   2355   return 1;
   2356 }
   2357 
   2358 
   2359 static const uint8_t no_https_seed[] = { 0 };
   2360 
   2361 
   2362 static size_t
   2363 fuzz_seed_count (void)
   2364 {
   2365   return 1;
   2366 }
   2367 
   2368 
   2369 static const uint8_t *
   2370 fuzz_seed_get (size_t idx,
   2371                size_t *len)
   2372 {
   2373   (void) idx;
   2374   *len = sizeof (no_https_seed);
   2375   return no_https_seed;
   2376 }
   2377 
   2378 
   2379 #endif /* ! HTTPS_SUPPORT */
   2380 
   2381 /* end of fuzz_tls.c */