anastasis

Credential backup and recovery protocol and service
Log | Files | Refs | Submodules | README | LICENSE

test_validation.c (5614B)


      1 /*
      2   This file is part of Anastasis
      3   Copyright (C) 2026 Anastasis SARL
      4 
      5   Anastasis is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13   You should have received a copy of the GNU General Public License along with
     14   Anastasis; see the file COPYING.GPL.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file reducer/test_validation.c
     18  * @brief testcase for the validation-logic dispatch table
     19  * @author Christian Grothoff
     20  */
     21 #include "platform.h"
     22 #include <gnunet/gnunet_util_lib.h>
     23 #include "validation.h"
     24 
     25 /**
     26  * Every name that appears as a "validation-logic" value in
     27  * contrib/redux.*.json.  All of them must resolve.
     28  */
     29 static const char *known[] = {
     30   "BE_NRN_check",
     31   "CH_AHV_check",
     32   "CZ_BN_check",
     33   "DE_SVN_check",
     34   "DE_TIN_check",
     35   "ES_DNI_check",
     36   "FR_INSEE_check",
     37   "IN_AADHAR_check",
     38   "IT_CF_check",
     39   "NL_BSN_check",
     40   "XX_SQUARE_check",
     41   "XY_PRIME_check",
     42   NULL
     43 };
     44 
     45 /**
     46  * Names that must NOT resolve; "system" and "abort" are the reason the old
     47  * dlsym() dispatch was a remote code execution bug.
     48  */
     49 static const char *unknown[] = {
     50   "system",
     51   "abort",
     52   "printf",
     53   "",
     54   "NL_BSN_check ",
     55   "nl_bsn_check",
     56   NULL
     57 };
     58 
     59 
     60 int
     61 main (int argc,
     62       const char *const argv[])
     63 {
     64   GNUNET_log_setup ("test-validation",
     65                     "WARNING",
     66                     NULL);
     67   for (unsigned int i = 0; NULL != known[i]; i++)
     68     if (NULL == ANASTASIS_REDUX_validation_lookup_ (known[i]))
     69     {
     70       GNUNET_break (0);
     71       fprintf (stderr,
     72                "validation logic `%s' does not resolve\n",
     73                known[i]);
     74       return 1;
     75     }
     76   for (unsigned int i = 0; NULL != unknown[i]; i++)
     77     if (NULL != ANASTASIS_REDUX_validation_lookup_ (unknown[i]))
     78     {
     79       GNUNET_break (0);
     80       fprintf (stderr,
     81                "`%s' must not resolve to a validation function\n",
     82                unknown[i]);
     83       return 1;
     84     }
     85   if (NULL != ANASTASIS_REDUX_validation_lookup_ (NULL))
     86   {
     87     GNUNET_break (0);
     88     return 1;
     89   }
     90 
     91   /* Belgian national register number: 93.05.18-223.61 is the documented
     92      example; 97 - (930518223 % 97) == 61.  As the century is not encoded we
     93      also accept the variant computed with the '2' prefix (check digits 90). */
     94   if (! BE_NRN_check ("93051822361"))
     95   {
     96     GNUNET_break (0);
     97     return 1;
     98   }
     99   if (! BE_NRN_check ("93051822390"))
    100   {
    101     GNUNET_break (0);
    102     return 1;
    103   }
    104   if (BE_NRN_check ("93051822362"))
    105   {
    106     GNUNET_break (0);
    107     return 1;
    108   }
    109   /* born in 2017: only the '2'-prefixed variant matches */
    110   if (! BE_NRN_check ("17060612328"))
    111   {
    112     GNUNET_break (0);
    113     return 1;
    114   }
    115   if (BE_NRN_check ("17060612327"))
    116   {
    117     GNUNET_break (0);
    118     return 1;
    119   }
    120   /* malformed input */
    121   if (BE_NRN_check (""))
    122   {
    123     GNUNET_break (0);
    124     return 1;
    125   }
    126   if (BE_NRN_check ("9305182236"))     /* too short */
    127   {
    128     GNUNET_break (0);
    129     return 1;
    130   }
    131   if (BE_NRN_check ("930518223611"))   /* too long */
    132   {
    133     GNUNET_break (0);
    134     return 1;
    135   }
    136   if (BE_NRN_check ("9305182236x"))    /* not a digit */
    137   {
    138     GNUNET_break (0);
    139     return 1;
    140   }
    141 
    142   /* French NIR: mainland and both Corsican department codes.  2A must map to
    143      19 and 2B to 18, so the two must not produce the same check digits. */
    144   if (! FR_INSEE_check ("180057512345627"))
    145   {
    146     GNUNET_break (0);
    147     return 1;
    148   }
    149   if (! FR_INSEE_check ("180052A12345684"))
    150   {
    151     GNUNET_break (0);
    152     return 1;
    153   }
    154   if (! FR_INSEE_check ("180052B12345614"))
    155   {
    156     GNUNET_break (0);
    157     return 1;
    158   }
    159   if (FR_INSEE_check ("180052A12345614"))   /* 2B's key on a 2A number */
    160   {
    161     GNUNET_break (0);
    162     return 1;
    163   }
    164   if (FR_INSEE_check ("180052C12345684"))   /* no such department letter */
    165   {
    166     GNUNET_break (0);
    167     return 1;
    168   }
    169 
    170   /* Czech birth numbers.  The modern form carries a check digit and must be
    171      divisible by 11; the nine-digit pre-1954 form has none and is accepted
    172      on the strength of its date alone. */
    173   if (! CZ_BN_check ("850615/0004"))
    174   {
    175     GNUNET_break (0);
    176     return 1;
    177   }
    178   if (! CZ_BN_check ("756203/0003"))     /* woman: month carries +50 */
    179   {
    180     GNUNET_break (0);
    181     return 1;
    182   }
    183   if (CZ_BN_check ("850615/0005"))       /* wrong check digit */
    184   {
    185     GNUNET_break (0);
    186     return 1;
    187   }
    188   if (! CZ_BN_check ("480615/123"))      /* born 1948: legacy form */
    189   {
    190     GNUNET_break (0);
    191     return 1;
    192   }
    193   if (CZ_BN_check ("850615/123"))        /* 1985 cannot use the legacy form */
    194   {
    195     GNUNET_break (0);
    196     return 1;
    197   }
    198   if (CZ_BN_check ("851315/0004"))       /* month 13 */
    199   {
    200     GNUNET_break (0);
    201     return 1;
    202   }
    203   if (CZ_BN_check ("850635/0004"))       /* day 35 */
    204   {
    205     GNUNET_break (0);
    206     return 1;
    207   }
    208   if (CZ_BN_check ("8506150004"))        /* the slash is not optional */
    209   {
    210     GNUNET_break (0);
    211     return 1;
    212   }
    213   if (CZ_BN_check ("482115/123"))        /* +20 months postdate the 9-digit form */
    214   {
    215     GNUNET_break (0);
    216     return 1;
    217   }
    218 
    219   /* Albania has no check-digit implementation, so contrib/redux.al.json
    220      carries no "validation-logic" at all and the name must not resolve. */
    221   if (NULL != ANASTASIS_REDUX_validation_lookup_ ("AL_NID_check"))
    222   {
    223     GNUNET_break (0);
    224     return 1;
    225   }
    226   return 0;
    227 }
    228 
    229 
    230 /* end of test_validation.c */