libmicrohttpd

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

test_dauth_userhash.c (24897B)


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