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 */