test_slug.c (3949B)
1 /* 2 This file is part of TALER 3 (C) 2026 Taler Systems SA 4 5 TALER 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 TALER 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 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file util/test_slug.c 18 * @brief Tests for slug and session ID validation 19 * @author Christian Grothoff 20 */ 21 #include "taler/taler_util.h" 22 23 24 static unsigned int 25 check_slug (void) 26 { 27 struct 28 { 29 const char *slug; 30 bool expected; 31 } tests[] = { 32 /* Valid slugs */ 33 {"a", true}, 34 {"instance-1", true}, 35 {"2026.216-EV3XB88000000", true}, 36 {"A.b_c:d~e", true}, 37 {"0123456789", true}, 38 {"...", true}, 39 40 /* Invalid slugs */ 41 {"", false}, /* empty */ 42 {".", false}, /* special path component */ 43 {"..", false}, /* special path component */ 44 {"a/b", false}, /* not a single component */ 45 {"a%2Fb", false}, /* percent-encoding */ 46 {"a b", false}, 47 {"a+b", false}, 48 {"a=b", false}, /* '=' is only for session IDs */ 49 {"a?b", false}, 50 {"a#b", false}, 51 {"a&b", false}, 52 {"a@b", false}, 53 /* Bytes >= 0x80 are rejected whatever the locale says about them: 54 "\u00e4" in UTF-8, and the same two bytes are each a letter in 55 ISO-8859-1. */ 56 {"a\xc3\xa4b", false}, 57 {"\xe4", false}, 58 }; 59 unsigned int failed = 0; 60 61 for (unsigned int i = 0; i<sizeof (tests) / sizeof (tests[0]); i++) 62 { 63 bool result = TALER_is_slug (tests[i].slug); 64 65 if (result == tests[i].expected) 66 continue; 67 failed++; 68 fprintf (stderr, 69 "FAIL: slug \"%s\" -> %s (expected %s)\n", 70 tests[i].slug, 71 result ? "VALID" : "INVALID", 72 tests[i].expected ? "VALID" : "INVALID"); 73 } 74 return failed; 75 } 76 77 78 static unsigned int 79 check_session_id (void) 80 { 81 struct 82 { 83 const char *session_id; 84 bool expected; 85 } tests[] = { 86 /* Valid session IDs */ 87 {"", true}, /* not session-bound */ 88 {"session-1", true}, 89 {"4322-6hvIP7UnmNDVjp5Intuf9jFK7MzW0ycEyxf5Mszl3xs=", true}, /* Paivana ID */ 90 {"a", true}, 91 {"A.b_c:d~e=", true}, 92 {"0123456789", true}, 93 {"...", true}, 94 95 /* Invalid session IDs */ 96 {".", false}, /* special path component */ 97 {"..", false}, /* special path component */ 98 {"a/b", false}, /* not a single component */ 99 {"a%2Fb", false}, /* percent-encoding */ 100 {"a b", false}, 101 {"a+b", false}, 102 {"a?b", false}, 103 {"a#b", false}, 104 {"a&b", false}, 105 {"a@b", false}, 106 {"a\xc3\xa4b", false}, 107 {"\xe4", false}, 108 }; 109 unsigned int failed = 0; 110 111 for (unsigned int i = 0; i<sizeof (tests) / sizeof (tests[0]); i++) 112 { 113 bool result = TALER_is_session_id (tests[i].session_id); 114 115 if (result == tests[i].expected) 116 continue; 117 failed++; 118 fprintf (stderr, 119 "FAIL: session ID \"%s\" -> %s (expected %s)\n", 120 tests[i].session_id, 121 result ? "VALID" : "INVALID", 122 tests[i].expected ? "VALID" : "INVALID"); 123 } 124 return failed; 125 } 126 127 128 int 129 main (int argc, 130 const char *const argv[]) 131 { 132 (void) argc; 133 (void) argv; 134 if (0 != check_slug ()) 135 return 1; 136 if (0 != check_session_id ()) 137 return 1; 138 return 0; 139 }