Line data Source code
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 1 : check_slug (void)
26 : {
27 : struct
28 : {
29 : const char *slug;
30 : bool expected;
31 1 : } 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 1 : unsigned int failed = 0;
60 :
61 21 : for (unsigned int i = 0; i<sizeof (tests) / sizeof (tests[0]); i++)
62 : {
63 20 : bool result = TALER_is_slug (tests[i].slug);
64 :
65 20 : if (result == tests[i].expected)
66 20 : continue;
67 0 : failed++;
68 0 : fprintf (stderr,
69 : "FAIL: slug \"%s\" -> %s (expected %s)\n",
70 : tests[i].slug,
71 : result ? "VALID" : "INVALID",
72 0 : tests[i].expected ? "VALID" : "INVALID");
73 : }
74 1 : return failed;
75 : }
76 :
77 :
78 : static unsigned int
79 1 : check_session_id (void)
80 : {
81 : struct
82 : {
83 : const char *session_id;
84 : bool expected;
85 1 : } 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 1 : unsigned int failed = 0;
110 :
111 20 : for (unsigned int i = 0; i<sizeof (tests) / sizeof (tests[0]); i++)
112 : {
113 19 : bool result = TALER_is_session_id (tests[i].session_id);
114 :
115 19 : if (result == tests[i].expected)
116 19 : continue;
117 0 : failed++;
118 0 : fprintf (stderr,
119 : "FAIL: session ID \"%s\" -> %s (expected %s)\n",
120 : tests[i].session_id,
121 : result ? "VALID" : "INVALID",
122 0 : tests[i].expected ? "VALID" : "INVALID");
123 : }
124 1 : return failed;
125 : }
126 :
127 :
128 : int
129 1 : main (int argc,
130 : const char *const argv[])
131 : {
132 : (void) argc;
133 : (void) argv;
134 1 : if (0 != check_slug ())
135 0 : return 1;
136 1 : if (0 != check_session_id ())
137 0 : return 1;
138 1 : return 0;
139 : }
|