libmicrohttpd

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

test_dauth_userhash.c (25064B)


      1 /*
      2   This file is part of libmicrohttpd
      3   Copyright (C) 2022 Evgeny Grin (Karlson2)
      4 
      5   This test tool is free software; you can redistribute it and/or
      6   modify it under the terms of the GNU General Public License as
      7   published by the Free Software Foundation; either version 2, or
      8   (at your option) any later version.
      9 
     10   This test tool 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; if not, write to the Free Software
     17   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     18 */
     19 
     20 /**
     21  * @file microhttpd/test_dauth_userhash.c
     22  * @brief  Tests for Digest Auth calculations of userhash
     23  * @author Karlson2k (Evgeny Grin)
     24  */
     25 
     26 #include "mhd_options.h"
     27 #include <stdio.h>
     28 #include <stdlib.h>
     29 #include <string.h>
     30 #include "microhttpd.h"
     31 #include "test_helpers.h"
     32 
     33 /* Turn any MHD_PANIC() or failing mhd_assert() reached from this
     34    test into a marked, classifiable test error (TESTING.md, P5). */
     35 #include "mhd_panic_tripwire.h"
     36 
     37 #if defined(MHD_HTTPS_REQUIRE_GCRYPT) && \
     38   (defined(MHD_SHA256_TLSLIB) || defined(MHD_MD5_TLSLIB))
     39 #define NEED_GCRYP_INIT 1
     40 #include <gcrypt.h>
     41 #endif /* MHD_HTTPS_REQUIRE_GCRYPT && (MHD_SHA256_TLSLIB || MHD_MD5_TLSLIB) */
     42 
     43 static int verbose = 1; /* verbose level (0-1)*/
     44 
     45 /* Declarations and data */
     46 
     47 struct data_md5
     48 {
     49   unsigned int line_num;
     50   const char *const username;
     51   const char *const realm;
     52   const uint8_t hash[MHD_MD5_DIGEST_SIZE];
     53 };
     54 
     55 
     56 static const struct data_md5 md5_tests[] = {
     57   {__LINE__,
     58    "u", "r",
     59    {0xba, 0x84, 0xbe, 0x20, 0x3f, 0xdf, 0xc7, 0xd3, 0x4e, 0x05, 0x4a, 0x76,
     60     0xd2, 0x85, 0xd0, 0xc9}},
     61   {__LINE__,
     62    "testuser", "testrealm",
     63    {0xab, 0xae, 0x15, 0x95, 0x24, 0xe5, 0x17, 0xbf, 0x48, 0xf4, 0x4a, 0xab,
     64     0xfe, 0xb9, 0x37, 0x40}},
     65   {__LINE__,
     66    "test_user", "TestRealm", /* Values from testcurl/test_digestauth2.c */
     67    {0xc5, 0x3c, 0x60, 0x15, 0x03, 0xff, 0x17, 0x6f, 0x18, 0xf6, 0x23, 0x72,
     68     0x5f, 0xba, 0x42, 0x81}},
     69   {__LINE__,
     70    "Mufasa", "myhost@testrealm.com",
     71    {0x26, 0x45, 0xae, 0x13, 0xd1, 0xa2, 0xa6, 0x9e, 0xd2, 0x6d, 0xd2, 0x1a,
     72     0xa5, 0x52, 0x86, 0xe3}},
     73   {__LINE__,
     74    "Mufasa", "myhost@example.com",
     75    {0x4f, 0xc8, 0x64, 0x02, 0xd7, 0x18, 0x5d, 0x7b, 0x38, 0xd4, 0x38, 0xad,
     76     0xd5, 0x5a, 0x35, 0x84}},
     77   {__LINE__,
     78    "Mufasa", "http-auth@example.org",
     79    {0x42, 0x38, 0xf3, 0xa1, 0x61, 0x67, 0x37, 0x3f, 0xeb, 0xb9, 0xbc, 0x4d,
     80     0x43, 0xdb, 0x9c, 0xc4}},
     81   {__LINE__,
     82    "J" "\xC3\xA4" "s" "\xC3\xB8" "n Doe" /* "Jäsøn Doe" */, "api@example.org",
     83    {0x2e, 0x06, 0x3f, 0xa2, 0xc5, 0x4d, 0xea, 0x1c, 0x36, 0x80, 0x8b, 0x7a,
     84     0x6e, 0x3b, 0x14, 0xc9}}
     85 };
     86 
     87 struct data_sha256
     88 {
     89   unsigned int line_num;
     90   const char *const username;
     91   const char *const realm;
     92   const uint8_t hash[MHD_SHA256_DIGEST_SIZE];
     93 };
     94 
     95 static const struct data_sha256 sha256_tests[] = {
     96   {__LINE__,
     97    "u", "r",
     98    {0x1d, 0x8a, 0x03, 0xa6, 0xe2, 0x1a, 0x4c, 0xe7, 0x75, 0x06, 0x0e, 0xa5,
     99     0x73, 0x60, 0x32, 0x9a, 0xc7, 0x50, 0xde, 0xa5, 0xd8, 0x47, 0x29, 0x7b,
    100     0x42, 0xf0, 0xd4, 0x65, 0x39, 0xaf, 0x8a, 0xb2}},
    101   {__LINE__,
    102    "testuser", "testrealm",
    103    {0x75, 0xaf, 0x8a, 0x35, 0x00, 0xf7, 0x71, 0xe5, 0x8a, 0x52, 0x09, 0x3a,
    104     0x25, 0xe7, 0x90, 0x5d, 0x6e, 0x42, 0x8a, 0x51, 0x12, 0x85, 0xc1, 0x2e,
    105     0xa1, 0x42, 0x0c, 0x73, 0x07, 0x8d, 0xfd, 0x61}},
    106   {__LINE__,
    107    "test_user", "TestRealm", /* Values from testcurl/test_digestauth2.c */
    108    {0x09, 0x0c, 0x7e, 0x06, 0xb7, 0x7d, 0x66, 0x14, 0xcf, 0x5f, 0xe6, 0xca,
    109     0xfa, 0x00, 0x4d, 0x2e, 0x5f, 0x8f, 0xb3, 0x6b, 0xa4, 0x5a, 0x0e, 0x35,
    110     0xea, 0xcb, 0x2e, 0xb7, 0x72, 0x8f, 0x34, 0xde}},
    111   {__LINE__,
    112    "Mufasa", "myhost@testrealm.com",
    113    {0x92, 0x9f, 0xac, 0x9e, 0x6c, 0x8b, 0x76, 0xcc, 0xab, 0xa9, 0xe0, 0x6f,
    114     0xf6, 0x4d, 0xf2, 0x6f, 0xcb, 0x40, 0x56, 0x4c, 0x19, 0x9c, 0x32, 0xd9,
    115     0xea, 0xd9, 0x12, 0x4b, 0x25, 0x34, 0xe1, 0xf9}},
    116   {__LINE__,
    117    "Mufasa", "myhost@example.com",
    118    {0x97, 0x06, 0xf0, 0x07, 0x1c, 0xec, 0x05, 0x3f, 0x88, 0x22, 0xb6, 0x63,
    119     0x69, 0xc4, 0xa4, 0x00, 0x39, 0x79, 0xb7, 0xe7, 0x42, 0xb7, 0x4e, 0x42,
    120     0x59, 0x63, 0x57, 0xf4, 0xd3, 0x02, 0xae, 0x16}},
    121   {__LINE__,
    122    "Mufasa", "http-auth@example.org",
    123    {0xa9, 0x47, 0xaa, 0xd2, 0x05, 0xe8, 0x0e, 0x42, 0x99, 0x58, 0xa3, 0x87,
    124     0x39, 0x49, 0x44, 0xc6, 0xb4, 0x96, 0x30, 0x1e, 0x79, 0xf8, 0x9d, 0x35,
    125     0xa4, 0xcc, 0x23, 0xb6, 0xee, 0x12, 0xb5, 0xb6}},
    126   {__LINE__,
    127    "J" "\xC3\xA4" "s" "\xC3\xB8" "n Doe" /* "Jäsøn Doe" */, "api@example.org",
    128    {0x5a, 0x1a, 0x8a, 0x47, 0xdf, 0x5c, 0x29, 0x85, 0x51, 0xb9, 0xb4, 0x2b,
    129     0xa9, 0xb0, 0x58, 0x35, 0x17, 0x4a, 0x5b, 0xd7, 0xd5, 0x11, 0xff, 0x7f,
    130     0xe9, 0x19, 0x1d, 0x8e, 0x94, 0x6f, 0xc4, 0xe7}}
    131 };
    132 
    133 struct data_sha512_256
    134 {
    135   unsigned int line_num;
    136   const char *const username;
    137   const char *const realm;
    138   const uint8_t hash[MHD_SHA512_256_DIGEST_SIZE];
    139 };
    140 
    141 
    142 static const struct data_sha512_256 sha512_256_tests[] = {
    143   {__LINE__,
    144    "u", "r",
    145    {0xc7, 0x38, 0xf2, 0xad, 0x40, 0x1b, 0xc8, 0x7a, 0x71, 0xfe, 0x78, 0x09,
    146     0x60, 0x15, 0xc9, 0x7b, 0x9a, 0x26, 0xd5, 0x5f, 0x15, 0xe9, 0xf5, 0x0a,
    147     0xc3, 0xa6, 0xde, 0x73, 0xdd, 0xcd, 0x3d, 0x08}},
    148   {__LINE__,
    149    "testuser", "testrealm",
    150    {0x4f, 0x69, 0x1e, 0xe9, 0x50, 0x8a, 0xe4, 0x55, 0x21, 0x32, 0x9e, 0xcf,
    151     0xd4, 0x91, 0xf7, 0xe2, 0x77, 0x4b, 0x6f, 0xb8, 0x60, 0x2c, 0x14, 0x86,
    152     0xad, 0x94, 0x9d, 0x1c, 0x23, 0xd8, 0xa1, 0xf5}},
    153   {__LINE__,
    154    "test_user", "TestRealm", /* Values from testcurl/test_digestauth2.c */
    155    {0x62, 0xe1, 0xac, 0x9f, 0x6c, 0xb1, 0xeb, 0x26, 0xaa, 0x75, 0xeb, 0x5d,
    156     0x46, 0xef, 0xcd, 0xc8, 0x9c, 0xcb, 0xa7, 0x81, 0xf0, 0xf9, 0xf7, 0x2f,
    157     0x6a, 0xfd, 0xb9, 0x42, 0x65, 0xd9, 0xa7, 0x9a}},
    158   {__LINE__,
    159    "Mufasa", "myhost@testrealm.com",
    160    {0xbd, 0x3e, 0xbc, 0x30, 0x10, 0x0b, 0x7c, 0xf1, 0x61, 0x45, 0x6c, 0xfe,
    161     0x64, 0x1c, 0x4c, 0xd2, 0x82, 0xe0, 0x62, 0x6e, 0x2c, 0x5e, 0x09, 0xc2,
    162     0x4c, 0x90, 0xb1, 0x60, 0x8a, 0xec, 0x28, 0x64}},
    163   {__LINE__,
    164    "Mufasa", "myhost@example.com",
    165    {0xea, 0x4b, 0x59, 0x37, 0xde, 0x2c, 0x4e, 0x9f, 0x16, 0xf9, 0x9c, 0x31,
    166     0x01, 0xb6, 0xdd, 0xf8, 0x8c, 0x85, 0xd7, 0xe8, 0xf1, 0x75, 0x90, 0xd0,
    167     0x63, 0x2a, 0x75, 0x75, 0xe4, 0x80, 0x13, 0x69}},
    168   {__LINE__,
    169    "Mufasa", "http-auth@example.org",
    170    {0xe2, 0xdf, 0xab, 0xd1, 0xa9, 0x6d, 0xdf, 0x86, 0x77, 0x10, 0xb6, 0x53,
    171     0xb6, 0xe6, 0x85, 0x7d, 0x1f, 0x14, 0x70, 0x86, 0xde, 0x7d, 0x7e, 0xf7,
    172     0x9d, 0xcd, 0x24, 0x98, 0x59, 0x87, 0x25, 0x70}},
    173   {__LINE__,
    174    "J" "\xC3\xA4" "s" "\xC3\xB8" "n Doe" /* "Jäsøn Doe" */, "api@example.org",
    175    {0x79, 0x32, 0x63, 0xca, 0xab, 0xb7, 0x07, 0xa5, 0x62, 0x11, 0x94, 0x0d,
    176     0x90, 0x41, 0x1e, 0xa4, 0xa5, 0x75, 0xad, 0xec, 0xcb, 0x7e, 0x36, 0x0a,
    177     0xeb, 0x62, 0x4e, 0xd0, 0x6e, 0xce, 0x9b, 0x0b}}
    178 };
    179 
    180 
    181 /*
    182  *  Helper functions
    183  */
    184 
    185 /**
    186  * Print bin as lower case hex
    187  *
    188  * @param bin binary data
    189  * @param len number of bytes in bin
    190  * @param hex pointer to len*2+1 bytes buffer
    191  */
    192 static void
    193 bin2hex (const uint8_t *bin,
    194          size_t len,
    195          char *hex)
    196 {
    197   while (len-- > 0)
    198   {
    199     unsigned int b1, b2;
    200     b1 = (*bin >> 4) & 0xf;
    201     *hex++ = (char) ((b1 > 9) ? (b1 + 'a' - 10) : (b1 + '0'));
    202     b2 = *bin++ & 0xf;
    203     *hex++ = (char) ((b2 > 9) ? (b2 + 'a' - 10) : (b2 + '0'));
    204   }
    205   *hex = 0;
    206 }
    207 
    208 
    209 /* Tests */
    210 
    211 static unsigned int
    212 check_md5 (const struct data_md5 *const data)
    213 {
    214   static const enum MHD_DigestAuthAlgo3 algo3 = MHD_DIGEST_AUTH_ALGO3_MD5;
    215   uint8_t hash_bin[MHD_MD5_DIGEST_SIZE];
    216   char hash_hex[MHD_MD5_DIGEST_SIZE * 2 + 1];
    217   char expected_hex[MHD_MD5_DIGEST_SIZE * 2 + 1];
    218   const char *func_name;
    219   unsigned int failed = 0;
    220 
    221   func_name = "MHD_digest_auth_calc_userhash";
    222   if (MHD_YES != MHD_digest_auth_calc_userhash (algo3,
    223                                                 data->username, data->realm,
    224                                                 hash_bin, sizeof(hash_bin)))
    225   {
    226     failed++;
    227     fprintf (stderr,
    228              "FAILED: %s() has not returned MHD_YES.\n",
    229              func_name);
    230   }
    231   else if (0 != memcmp (hash_bin, data->hash, sizeof(data->hash)))
    232   {
    233     failed++;
    234     bin2hex (hash_bin, sizeof(hash_bin), hash_hex);
    235     bin2hex (data->hash, sizeof(data->hash), expected_hex);
    236     fprintf (stderr,
    237              "FAILED: %s() produced wrong hash. "
    238              "Calculated digest %s, expected digest %s.\n",
    239              func_name,
    240              hash_hex, expected_hex);
    241   }
    242 
    243   func_name = "MHD_digest_auth_calc_userhash_hex";
    244   if (MHD_YES !=
    245       MHD_digest_auth_calc_userhash_hex (algo3,
    246                                          data->username, data->realm,
    247                                          hash_hex, sizeof(hash_hex)))
    248   {
    249     failed++;
    250     fprintf (stderr,
    251              "FAILED: %s() has not returned MHD_YES.\n",
    252              func_name);
    253   }
    254   else if (sizeof(hash_hex) - 1 != strlen (hash_hex))
    255   {
    256     failed++;
    257     fprintf (stderr,
    258              "FAILED: %s produced hash with wrong length. "
    259              "Calculated length %u, expected digest %u.\n",
    260              func_name,
    261              (unsigned) strlen (hash_hex),
    262              (unsigned) (sizeof(hash_hex) - 1));
    263   }
    264   else
    265   {
    266     bin2hex (data->hash, sizeof(data->hash), expected_hex);
    267     if (0 != memcmp (hash_hex, expected_hex, sizeof(hash_hex)))
    268     {
    269       failed++;
    270       fprintf (stderr,
    271                "FAILED: %s() produced wrong hash. "
    272                "Calculated digest %s, expected digest %s.\n",
    273                func_name,
    274                hash_hex, expected_hex);
    275     }
    276   }
    277 
    278   if (failed)
    279   {
    280     fprintf (stderr,
    281              "The check failed for data located at line: %u.\n",
    282              data->line_num);
    283     fflush (stderr);
    284   }
    285   else if (verbose)
    286   {
    287     printf ("PASSED: check for data at line: %u.\n",
    288             data->line_num);
    289   }
    290   return failed ? 1 : 0;
    291 }
    292 
    293 
    294 static unsigned int
    295 test_md5 (void)
    296 {
    297   unsigned int num_failed = 0;
    298   size_t i;
    299 
    300   for (i = 0; i < sizeof(md5_tests) / sizeof(md5_tests[0]); i++)
    301     num_failed += check_md5 (md5_tests + i);
    302   return num_failed;
    303 }
    304 
    305 
    306 static unsigned int
    307 test_md5_failure (void)
    308 {
    309   static const enum MHD_DigestAuthAlgo3 algo3 = MHD_DIGEST_AUTH_ALGO3_MD5;
    310   uint8_t hash_bin[MHD_MD5_DIGEST_SIZE];
    311   char hash_hex[MHD_MD5_DIGEST_SIZE * 2 + 1];
    312   const char *func_name;
    313   unsigned int failed = 0;
    314 
    315   func_name = "MHD_digest_auth_calc_userhash";
    316   if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
    317                                                "u", "r",
    318                                                hash_bin, sizeof(hash_bin) - 1))
    319   {
    320     failed++;
    321     fprintf (stderr,
    322              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    323              func_name, (unsigned) __LINE__);
    324   }
    325   if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
    326                                                "u", "r",
    327                                                hash_bin, 0))
    328   {
    329     failed++;
    330     fprintf (stderr,
    331              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    332              func_name, (unsigned) __LINE__);
    333   }
    334   if (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_MD5))
    335   {
    336     if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
    337                                                  "u", "r",
    338                                                  hash_bin, sizeof(hash_bin)))
    339     {
    340       failed++;
    341       fprintf (stderr,
    342                "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    343                func_name, (unsigned) __LINE__);
    344     }
    345   }
    346 
    347   func_name = "MHD_digest_auth_calc_userhash_hex";
    348   if (MHD_NO !=
    349       MHD_digest_auth_calc_userhash_hex (algo3,
    350                                          "u", "r",
    351                                          hash_hex, sizeof(hash_hex) - 1))
    352   {
    353     failed++;
    354     fprintf (stderr,
    355              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    356              func_name, (unsigned) __LINE__);
    357   }
    358   if (MHD_NO !=
    359       MHD_digest_auth_calc_userhash_hex (algo3,
    360                                          "u", "r",
    361                                          hash_hex, 0))
    362   {
    363     failed++;
    364     fprintf (stderr,
    365              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    366              func_name, (unsigned) __LINE__);
    367   }
    368   if (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_MD5))
    369   {
    370     if (MHD_NO !=
    371         MHD_digest_auth_calc_userhash_hex (algo3,
    372                                            "u", "r",
    373                                            hash_hex, sizeof(hash_hex)))
    374     {
    375       failed++;
    376       fprintf (stderr,
    377                "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    378                func_name, (unsigned) __LINE__);
    379     }
    380   }
    381 
    382   if (! failed && verbose)
    383   {
    384     printf ("PASSED: all checks with expected MHD_NO result near line: %u.\n",
    385             (unsigned) __LINE__);
    386   }
    387   return failed ? 1 : 0;
    388 }
    389 
    390 
    391 static unsigned int
    392 check_sha256 (const struct data_sha256 *const data)
    393 {
    394   static const enum MHD_DigestAuthAlgo3 algo3 = MHD_DIGEST_AUTH_ALGO3_SHA256;
    395   uint8_t hash_bin[MHD_SHA256_DIGEST_SIZE];
    396   char hash_hex[MHD_SHA256_DIGEST_SIZE * 2 + 1];
    397   char expected_hex[MHD_SHA256_DIGEST_SIZE * 2 + 1];
    398   const char *func_name;
    399   unsigned int failed = 0;
    400 
    401   func_name = "MHD_digest_auth_calc_userhash";
    402   if (MHD_YES != MHD_digest_auth_calc_userhash (algo3,
    403                                                 data->username, data->realm,
    404                                                 hash_bin, sizeof(hash_bin)))
    405   {
    406     failed++;
    407     fprintf (stderr,
    408              "FAILED: %s() has not returned MHD_YES.\n",
    409              func_name);
    410   }
    411   else if (0 != memcmp (hash_bin, data->hash, sizeof(data->hash)))
    412   {
    413     failed++;
    414     bin2hex (hash_bin, sizeof(hash_bin), hash_hex);
    415     bin2hex (data->hash, sizeof(data->hash), expected_hex);
    416     fprintf (stderr,
    417              "FAILED: %s() produced wrong hash. "
    418              "Calculated digest %s, expected digest %s.\n",
    419              func_name,
    420              hash_hex, expected_hex);
    421   }
    422 
    423   func_name = "MHD_digest_auth_calc_userhash_hex";
    424   if (MHD_YES !=
    425       MHD_digest_auth_calc_userhash_hex (algo3,
    426                                          data->username, data->realm,
    427                                          hash_hex, sizeof(hash_hex)))
    428   {
    429     failed++;
    430     fprintf (stderr,
    431              "FAILED: %s() has not returned MHD_YES.\n",
    432              func_name);
    433   }
    434   else if (sizeof(hash_hex) - 1 != strlen (hash_hex))
    435   {
    436     failed++;
    437     fprintf (stderr,
    438              "FAILED: %s produced hash with wrong length. "
    439              "Calculated length %u, expected digest %u.\n",
    440              func_name,
    441              (unsigned) strlen (hash_hex),
    442              (unsigned) (sizeof(hash_hex) - 1));
    443   }
    444   else
    445   {
    446     bin2hex (data->hash, sizeof(data->hash), expected_hex);
    447     if (0 != memcmp (hash_hex, expected_hex, sizeof(hash_hex)))
    448     {
    449       failed++;
    450       fprintf (stderr,
    451                "FAILED: %s() produced wrong hash. "
    452                "Calculated digest %s, expected digest %s.\n",
    453                func_name,
    454                hash_hex, expected_hex);
    455     }
    456   }
    457 
    458   if (failed)
    459   {
    460     fprintf (stderr,
    461              "The check failed for data located at line: %u.\n",
    462              data->line_num);
    463     fflush (stderr);
    464   }
    465   else if (verbose)
    466   {
    467     printf ("PASSED: check for data at line: %u.\n",
    468             data->line_num);
    469   }
    470   return failed ? 1 : 0;
    471 }
    472 
    473 
    474 static unsigned int
    475 test_sha256 (void)
    476 {
    477   unsigned int num_failed = 0;
    478   size_t i;
    479 
    480   for (i = 0; i < sizeof(sha256_tests) / sizeof(sha256_tests[0]); i++)
    481     num_failed += check_sha256 (sha256_tests + i);
    482   return num_failed;
    483 }
    484 
    485 
    486 static unsigned int
    487 test_sha256_failure (void)
    488 {
    489   static const enum MHD_DigestAuthAlgo3 algo3 = MHD_DIGEST_AUTH_ALGO3_SHA256;
    490   uint8_t hash_bin[MHD_SHA256_DIGEST_SIZE];
    491   char hash_hex[MHD_SHA256_DIGEST_SIZE * 2 + 1];
    492   const char *func_name;
    493   unsigned int failed = 0;
    494 
    495   func_name = "MHD_digest_auth_calc_userhash";
    496   if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
    497                                                "u", "r",
    498                                                hash_bin, sizeof(hash_bin) - 1))
    499   {
    500     failed++;
    501     fprintf (stderr,
    502              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    503              func_name, (unsigned) __LINE__);
    504   }
    505   if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
    506                                                "u", "r",
    507                                                hash_bin, 0))
    508   {
    509     failed++;
    510     fprintf (stderr,
    511              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    512              func_name, (unsigned) __LINE__);
    513   }
    514   if (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA256))
    515   {
    516     if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
    517                                                  "u", "r",
    518                                                  hash_bin, sizeof(hash_bin)))
    519     {
    520       failed++;
    521       fprintf (stderr,
    522                "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    523                func_name, (unsigned) __LINE__);
    524     }
    525   }
    526 
    527   func_name = "MHD_digest_auth_calc_userhash_hex";
    528   if (MHD_NO !=
    529       MHD_digest_auth_calc_userhash_hex (algo3,
    530                                          "u", "r",
    531                                          hash_hex, sizeof(hash_hex) - 1))
    532   {
    533     failed++;
    534     fprintf (stderr,
    535              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    536              func_name, (unsigned) __LINE__);
    537   }
    538   if (MHD_NO !=
    539       MHD_digest_auth_calc_userhash_hex (algo3,
    540                                          "u", "r",
    541                                          hash_hex, 0))
    542   {
    543     failed++;
    544     fprintf (stderr,
    545              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    546              func_name, (unsigned) __LINE__);
    547   }
    548   if (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA256))
    549   {
    550     if (MHD_NO !=
    551         MHD_digest_auth_calc_userhash_hex (algo3,
    552                                            "u", "r",
    553                                            hash_hex, sizeof(hash_hex)))
    554     {
    555       failed++;
    556       fprintf (stderr,
    557                "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    558                func_name, (unsigned) __LINE__);
    559     }
    560   }
    561 
    562   if (! failed && verbose)
    563   {
    564     printf ("PASSED: all checks with expected MHD_NO result near line: %u.\n",
    565             (unsigned) __LINE__);
    566   }
    567   return failed ? 1 : 0;
    568 }
    569 
    570 
    571 static unsigned int
    572 check_sha512_256 (const struct data_sha512_256 *const data)
    573 {
    574   static const enum MHD_DigestAuthAlgo3 algo3 =
    575     MHD_DIGEST_AUTH_ALGO3_SHA512_256;
    576   uint8_t hash_bin[MHD_SHA512_256_DIGEST_SIZE];
    577   char hash_hex[MHD_SHA512_256_DIGEST_SIZE * 2 + 1];
    578   char expected_hex[MHD_SHA512_256_DIGEST_SIZE * 2 + 1];
    579   const char *func_name;
    580   unsigned int failed = 0;
    581 
    582   func_name = "MHD_digest_auth_calc_userhash";
    583   if (MHD_YES != MHD_digest_auth_calc_userhash (algo3,
    584                                                 data->username, data->realm,
    585                                                 hash_bin, sizeof(hash_bin)))
    586   {
    587     failed++;
    588     fprintf (stderr,
    589              "FAILED: %s() has not returned MHD_YES.\n",
    590              func_name);
    591   }
    592   else if (0 != memcmp (hash_bin, data->hash, sizeof(data->hash)))
    593   {
    594     failed++;
    595     bin2hex (hash_bin, sizeof(hash_bin), hash_hex);
    596     bin2hex (data->hash, sizeof(data->hash), expected_hex);
    597     fprintf (stderr,
    598              "FAILED: %s() produced wrong hash. "
    599              "Calculated digest %s, expected digest %s.\n",
    600              func_name,
    601              hash_hex, expected_hex);
    602   }
    603 
    604   func_name = "MHD_digest_auth_calc_userhash_hex";
    605   if (MHD_YES !=
    606       MHD_digest_auth_calc_userhash_hex (algo3,
    607                                          data->username, data->realm,
    608                                          hash_hex, sizeof(hash_hex)))
    609   {
    610     failed++;
    611     fprintf (stderr,
    612              "FAILED: %s() has not returned MHD_YES.\n",
    613              func_name);
    614   }
    615   else if (sizeof(hash_hex) - 1 != strlen (hash_hex))
    616   {
    617     failed++;
    618     fprintf (stderr,
    619              "FAILED: %s produced hash with wrong length. "
    620              "Calculated length %u, expected digest %u.\n",
    621              func_name,
    622              (unsigned) strlen (hash_hex),
    623              (unsigned) (sizeof(hash_hex) - 1));
    624   }
    625   else
    626   {
    627     bin2hex (data->hash, sizeof(data->hash), expected_hex);
    628     if (0 != memcmp (hash_hex, expected_hex, sizeof(hash_hex)))
    629     {
    630       failed++;
    631       fprintf (stderr,
    632                "FAILED: %s() produced wrong hash. "
    633                "Calculated digest %s, expected digest %s.\n",
    634                func_name,
    635                hash_hex, expected_hex);
    636     }
    637   }
    638 
    639   if (failed)
    640   {
    641     fprintf (stderr,
    642              "The check failed for data located at line: %u.\n",
    643              data->line_num);
    644     fflush (stderr);
    645   }
    646   else if (verbose)
    647   {
    648     printf ("PASSED: check for data at line: %u.\n",
    649             data->line_num);
    650   }
    651   return failed ? 1 : 0;
    652 }
    653 
    654 
    655 static unsigned int
    656 test_sha512_256 (void)
    657 {
    658   unsigned int num_failed = 0;
    659   size_t i;
    660 
    661   for (i = 0; i < sizeof(sha512_256_tests) / sizeof(sha512_256_tests[0]); i++)
    662     num_failed += check_sha512_256 (sha512_256_tests + i);
    663   return num_failed;
    664 }
    665 
    666 
    667 static unsigned int
    668 test_sha512_256_failure (void)
    669 {
    670   static const enum MHD_DigestAuthAlgo3 algo3 =
    671     MHD_DIGEST_AUTH_ALGO3_SHA512_256;
    672   static const enum MHD_FEATURE feature = MHD_FEATURE_DIGEST_AUTH_SHA512_256;
    673   uint8_t hash_bin[MHD_SHA512_256_DIGEST_SIZE];
    674   char hash_hex[MHD_SHA512_256_DIGEST_SIZE * 2 + 1];
    675   const char *func_name;
    676   unsigned int failed = 0;
    677 
    678   func_name = "MHD_digest_auth_calc_userhash";
    679   if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
    680                                                "u", "r",
    681                                                hash_bin, sizeof(hash_bin) - 1))
    682   {
    683     failed++;
    684     fprintf (stderr,
    685              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    686              func_name, (unsigned) __LINE__);
    687   }
    688   if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
    689                                                "u", "r",
    690                                                hash_bin, 0))
    691   {
    692     failed++;
    693     fprintf (stderr,
    694              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    695              func_name, (unsigned) __LINE__);
    696   }
    697   if (MHD_NO == MHD_is_feature_supported (feature))
    698   {
    699     if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
    700                                                  "u", "r",
    701                                                  hash_bin, sizeof(hash_bin)))
    702     {
    703       failed++;
    704       fprintf (stderr,
    705                "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    706                func_name, (unsigned) __LINE__);
    707     }
    708   }
    709 
    710   func_name = "MHD_digest_auth_calc_userhash_hex";
    711   if (MHD_NO !=
    712       MHD_digest_auth_calc_userhash_hex (algo3,
    713                                          "u", "r",
    714                                          hash_hex, sizeof(hash_hex) - 1))
    715   {
    716     failed++;
    717     fprintf (stderr,
    718              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    719              func_name, (unsigned) __LINE__);
    720   }
    721   if (MHD_NO !=
    722       MHD_digest_auth_calc_userhash_hex (algo3,
    723                                          "u", "r",
    724                                          hash_hex, 0))
    725   {
    726     failed++;
    727     fprintf (stderr,
    728              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    729              func_name, (unsigned) __LINE__);
    730   }
    731   if (MHD_NO == MHD_is_feature_supported (feature))
    732   {
    733     if (MHD_NO !=
    734         MHD_digest_auth_calc_userhash_hex (algo3,
    735                                            "u", "r",
    736                                            hash_hex, sizeof(hash_hex)))
    737     {
    738       failed++;
    739       fprintf (stderr,
    740                "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    741                func_name, (unsigned) __LINE__);
    742     }
    743   }
    744 
    745   if (! failed && verbose)
    746   {
    747     printf ("PASSED: all checks with expected MHD_NO result near line: %u.\n",
    748             (unsigned) __LINE__);
    749   }
    750   return failed ? 1 : 0;
    751 }
    752 
    753 
    754 int
    755 main (int argc, char *argv[])
    756 {
    757   unsigned int num_failed = 0;
    758   (void) has_in_name; /* Mute compiler warning. */
    759   if (has_param (argc, argv, "-s") || has_param (argc, argv, "--silent"))
    760     verbose = 0;
    761 
    762 #ifdef NEED_GCRYP_INIT
    763   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
    764 #ifdef GCRYCTL_INITIALIZATION_FINISHED
    765   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
    766 #endif /* GCRYCTL_INITIALIZATION_FINISHED */
    767 #endif /* NEED_GCRYP_INIT */
    768 
    769   if (MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_MD5))
    770     num_failed += test_md5 ();
    771   num_failed += test_md5_failure ();
    772   if (MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA256))
    773     num_failed += test_sha256 ();
    774   num_failed += test_sha256_failure ();
    775   if (MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA512_256))
    776     num_failed += test_sha512_256 ();
    777   num_failed += test_sha512_256_failure ();
    778 
    779   return num_failed ? 1 : 0;
    780 }