Line data Source code
1 : /* Copyright (c) 2014-2021, The Tor Project, Inc. */
2 : /* See LICENSE for licensing information */
3 :
4 : #include "orconfig.h"
5 : #define KEYPIN_PRIVATE
6 : #include "core/or/or.h"
7 : #include "feature/dirauth/keypin.h"
8 :
9 : #include "test/test.h"
10 :
11 : static void
12 1 : test_keypin_parse_line(void *arg)
13 : {
14 1 : (void)arg;
15 1 : keypin_ent_t *ent = NULL;
16 :
17 : /* Good line */
18 1 : ent = keypin_parse_journal_line(
19 : "aGVyZSBpcyBhIGdvb2Qgc2hhMSE "
20 : "VGhpcyBlZDI1NTE5IHNjb2ZmcyBhdCB0aGUgc2hhMS4");
21 1 : tt_assert(ent);
22 1 : tt_mem_op(ent->rsa_id, OP_EQ, "here is a good sha1!", 20);
23 1 : tt_mem_op(ent->ed25519_key, OP_EQ, "This ed25519 scoffs at the sha1.", 32);
24 1 : tor_free(ent); ent = NULL;
25 :
26 : /* Good line with extra stuff we will ignore. */
27 1 : ent = keypin_parse_journal_line(
28 : "aGVyZSBpcyBhIGdvb2Qgc2hhMSE "
29 : "VGhpcyBlZDI1NTE5IHNjb2ZmcyBhdCB0aGUgc2hhMS4helloworld");
30 1 : tt_assert(ent);
31 1 : tt_mem_op(ent->rsa_id, OP_EQ, "here is a good sha1!", 20);
32 1 : tt_mem_op(ent->ed25519_key, OP_EQ, "This ed25519 scoffs at the sha1.", 32);
33 1 : tor_free(ent); ent = NULL;
34 :
35 : /* Bad line: no space in the middle. */
36 1 : ent = keypin_parse_journal_line(
37 : "aGVyZSBpcyBhIGdvb2Qgc2hhMSE?"
38 : "VGhpcyBlZDI1NTE5IHNjb2ZmcyBhdCB0aGUgc2hhMS4");
39 1 : tt_ptr_op(ent, OP_EQ, NULL);
40 :
41 : /* Bad line: bad base64 in RSA ID */
42 1 : ent = keypin_parse_journal_line(
43 : "aGVyZSBpcyBhIGdv!2Qgc2hhMSE "
44 : "VGhpcyBlZDI1NTE5IHNjb2ZmcyBhdCB0aGUgc2hhMS4");
45 1 : tt_ptr_op(ent, OP_EQ, NULL);
46 :
47 : /* Bad line: bad base64 in Ed25519 */
48 1 : ent = keypin_parse_journal_line(
49 : "aGVyZSBpcyBhIGdvb2Qgc2hhMSE "
50 : "VGhpcyBlZDI1NTE5IHNjb2ZmcyB!dCB0aGUgc2hhMS4");
51 1 : tt_ptr_op(ent, OP_EQ, NULL);
52 :
53 1 : done:
54 1 : tor_free(ent);
55 1 : }
56 :
57 : static smartlist_t *mock_addent_got = NULL;
58 : static void
59 14 : mock_addent(keypin_ent_t *ent)
60 : {
61 14 : smartlist_add(mock_addent_got, ent);
62 14 : keypin_add_entry_to_map__real(ent);
63 14 : }
64 :
65 : static void
66 1 : test_keypin_parse_file(void *arg)
67 : {
68 1 : (void)arg;
69 :
70 1 : mock_addent_got = smartlist_new();
71 1 : MOCK(keypin_add_entry_to_map, mock_addent);
72 :
73 : /* Simple, minimal, correct example. */
74 1 : const char data1[] =
75 : "PT09PT09PT09PT09PT09PT09PT0 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0\n"
76 : "TG9yYXggaXBzdW0gZ3J1dnZ1bHU cyB0aG5lZWQgYW1ldCwgc25lcmdlbGx5IG9uY2UtbGU\n"
77 : "ciBsZXJraW0sIHNlZCBkbyBiYXI YmFsb290IHRlbXBvciBnbHVwcGl0dXMgdXQgbGFib3I\n"
78 : "ZSBldCB0cnVmZnVsYSBtYWduYSA YWxpcXVhLiBVdCBlbmltIGFkIGdyaWNrbGUtZ3Jhc3M\n"
79 : "dmVuaWFtLCBxdWlzIG1pZmYtbXU ZmZlcmVkIGdhLXp1bXBjbyBsYWJvcmlzIG5pc2kgdXQ\n"
80 : "Y3J1ZmZ1bHVzIGV4IGVhIHNjaGw b3BwaXR5IGNvbnNlcXVhdC4gRHVpcyBhdXRlIHNuYXI\n"
81 : "Z2dsZSBpbiBzd29tZWVzd2FucyA aW4gdm9sdXB0YXRlIGF4ZS1oYWNrZXIgZXNzZSByaXA\n"
82 : "cHVsdXMgY3J1bW1paSBldSBtb28 ZiBudWxsYSBzbnV2di5QTFVHSFBMT1ZFUlhZWlpZLi4\n";
83 :
84 1 : tt_int_op(0, OP_EQ, keypin_load_journal_impl(data1, strlen(data1)));
85 1 : tt_int_op(8, OP_EQ, smartlist_len(mock_addent_got));
86 1 : keypin_ent_t *ent = smartlist_get(mock_addent_got, 2);
87 1 : tt_mem_op(ent->rsa_id, OP_EQ, "r lerkim, sed do bar", 20);
88 1 : tt_mem_op(ent->ed25519_key, OP_EQ, "baloot tempor gluppitus ut labor", 32);
89 :
90 : /* More complex example: weird lines, bogus lines,
91 : duplicate/conflicting lines */
92 1 : const char data2[] =
93 : "PT09PT09PT09PT09PT09PT09PT0 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0\n"
94 : "# This is a comment.\n"
95 : " \n"
96 : "QXQgdGhlIGVuZCBvZiB0aGUgeWU YXIgS3VycmVta2FybWVycnVrIHNhaWQgdG8gaGltLCA\n"
97 : "IllvdSBoYXZlIG1hZGUgYSBnb28 ZCBiZWdpbm5pbmcuIiBCdXQgbm8gbW9yZS4gV2l6YXI\n"
98 : "\n"
99 : "ZHMgc3BlYWsgdHJ1dGgsIGFuZCA aXQgd2FzIHRydWUgdGhhdCBhbGwgdGhlIG1hc3Rlcgo\n"
100 : "@reserved for a future extension \n"
101 : "eSBvZiBOYW1lcyB0aGF0IEdlZCA aGFkIHRvaWxlZCbyB3aW4gdGhhdCB5ZWFyIHdhcyA\n"
102 : "eSBvZiBOYW1lcyB0aGF0IEdlZCA aGFkIHRvaWxlZCbyB3aW4gdGhhdCB5ZWFyIHdhcy"
103 : "A line too long\n"
104 : "dGhlIG1lcmUgc3RhcnQgb2Ygd2g YXQgaGUgbXVzdCBnbyBvb!BsZWFybmluZy4uLi4uLi4\n"
105 : "ZHMgc3BlYWsgdaJ1dGgsIGFuZCA aXQgd2FzIHRydWUgdGhhdCBhbGwgdGhlIG1hc3Rlcgo\n"
106 : "ZHMgc3BlYWsgdHJ1dGgsIGFuZCA aXQgd2FzIHRydaUgdGhhdCBhbGwgdGhlIG1hc3Rlcgo\n"
107 : ;
108 :
109 1 : tt_int_op(0, OP_EQ, keypin_load_journal_impl(data2, strlen(data2)));
110 1 : tt_int_op(13, OP_EQ, smartlist_len(mock_addent_got));
111 1 : ent = smartlist_get(mock_addent_got, 9);
112 1 : tt_mem_op(ent->rsa_id, OP_EQ, "\"You have made a goo", 20);
113 1 : tt_mem_op(ent->ed25519_key, OP_EQ, "d beginning.\" But no more. Wizar", 32);
114 :
115 1 : ent = smartlist_get(mock_addent_got, 12);
116 1 : tt_mem_op(ent->rsa_id, OP_EQ, "ds speak truth, and ", 20);
117 1 : tt_mem_op(ent->ed25519_key, OP_EQ,
118 1 : "it was tru\xa5 that all the master\n", 32);
119 :
120 : /* File truncated before NL */
121 1 : const char data3[] =
122 : "Tm8gZHJhZ29uIGNhbiByZXNpc3Q IHRoZSBmYXNjaW5hdGlvbiBvZiByaWRkbGluZyB0YWw";
123 1 : tt_int_op(0, OP_EQ, keypin_load_journal_impl(data3, strlen(data3)));
124 1 : tt_int_op(14, OP_EQ, smartlist_len(mock_addent_got));
125 1 : ent = smartlist_get(mock_addent_got, 13);
126 1 : tt_mem_op(ent->rsa_id, OP_EQ, "No dragon can resist", 20);
127 1 : tt_mem_op(ent->ed25519_key, OP_EQ, " the fascination of riddling tal", 32);
128 :
129 1 : done:
130 1 : keypin_clear();
131 1 : smartlist_free(mock_addent_got);
132 1 : }
133 :
134 : #define ADD(a,b) keypin_check_and_add((const uint8_t*)(a),\
135 : (const uint8_t*)(b),0)
136 : #define LONE_RSA(a) keypin_check_lone_rsa((const uint8_t*)(a))
137 :
138 : static void
139 1 : test_keypin_add_entry(void *arg)
140 : {
141 1 : (void)arg;
142 1 : keypin_clear();
143 :
144 1 : tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("ambassadors-at-large",
145 : "bread-and-butter thing-in-itself"));
146 1 : tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("gentleman-adventurer",
147 : "cloak-and-dagger what's-his-face"));
148 :
149 1 : tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("ambassadors-at-large",
150 : "bread-and-butter thing-in-itself"));
151 1 : tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("ambassadors-at-large",
152 : "bread-and-butter thing-in-itself"));
153 1 : tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("gentleman-adventurer",
154 : "cloak-and-dagger what's-his-face"));
155 :
156 1 : tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("Johnnies-come-lately",
157 : "run-of-the-mill root-mean-square"));
158 :
159 1 : tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("gentleman-adventurer",
160 : "hypersentimental closefistedness"));
161 :
162 1 : tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("disestablismentarian",
163 : "cloak-and-dagger what's-his-face"));
164 :
165 1 : tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("gentleman-adventurer",
166 : "cloak-and-dagger what's-his-face"));
167 :
168 1 : tt_int_op(KEYPIN_NOT_FOUND, OP_EQ, LONE_RSA("Llanfairpwllgwyngyll"));
169 1 : tt_int_op(KEYPIN_MISMATCH, OP_EQ, LONE_RSA("Johnnies-come-lately"));
170 :
171 1 : done:
172 1 : keypin_clear();
173 1 : }
174 :
175 : static void
176 1 : test_keypin_journal(void *arg)
177 : {
178 1 : (void)arg;
179 1 : char *contents = NULL;
180 1 : const char *fname = get_fname("keypin-journal");
181 :
182 1 : tt_int_op(0, OP_EQ, keypin_load_journal(fname)); /* ENOENT is okay */
183 1 : update_approx_time(1217709000);
184 1 : tt_int_op(0, OP_EQ, keypin_open_journal(fname));
185 :
186 1 : tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("king-of-the-herrings",
187 : "good-for-nothing attorney-at-law"));
188 1 : tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("yellowish-red-yellow",
189 : "salt-and-pepper high-muck-a-muck"));
190 1 : tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("yellowish-red-yellow",
191 : "salt-and-pepper high-muck-a-muck"));
192 1 : keypin_close_journal();
193 1 : keypin_clear();
194 :
195 1 : tt_int_op(0, OP_EQ, keypin_load_journal(fname));
196 1 : update_approx_time(1231041600);
197 1 : tt_int_op(0, OP_EQ, keypin_open_journal(fname));
198 1 : tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("yellowish-red-yellow",
199 : "salt-and-pepper high-muck-a-muck"));
200 1 : tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("theatre-in-the-round",
201 : "holier-than-thou jack-in-the-box"));
202 1 : tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("no-deposit-no-return",
203 : "across-the-board will-o-the-wisp"));
204 1 : tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("intellectualizations",
205 : "salt-and-pepper high-muck-a-muck"));
206 1 : keypin_close_journal();
207 1 : keypin_clear();
208 :
209 1 : tt_int_op(0, OP_EQ, keypin_load_journal(fname));
210 1 : update_approx_time(1412278354);
211 1 : tt_int_op(0, OP_EQ, keypin_open_journal(fname));
212 1 : tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("yellowish-red-yellow",
213 : "salt-and-pepper high-muck-a-muck"));
214 1 : tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("intellectualizations",
215 : "salt-and-pepper high-muck-a-muck"));
216 1 : tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("theatre-in-the-round",
217 : "holier-than-thou jack-in-the-box"));
218 1 : tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("counterrevolutionary",
219 : "holier-than-thou jack-in-the-box"));
220 1 : tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("no-deposit-no-return",
221 : "floccinaucinihilipilificationism"));
222 1 : keypin_close_journal();
223 :
224 1 : contents = read_file_to_str(fname, RFTS_BIN, NULL);
225 1 : tt_assert(contents);
226 1 : tt_str_op(contents,OP_EQ,
227 : "\n"
228 : "@opened-at 2008-08-02 20:30:00\n"
229 : "a2luZy1vZi10aGUtaGVycmluZ3M Z29vZC1mb3Itbm90aGluZyBhdHRvcm5leS1hdC1sYXc\n"
230 : "eWVsbG93aXNoLXJlZC15ZWxsb3c c2FsdC1hbmQtcGVwcGVyIGhpZ2gtbXVjay1hLW11Y2s\n"
231 : "\n"
232 : "@opened-at 2009-01-04 04:00:00\n"
233 : "dGhlYXRyZS1pbi10aGUtcm91bmQ aG9saWVyLXRoYW4tdGhvdSBqYWNrLWluLXRoZS1ib3g\n"
234 : "bm8tZGVwb3NpdC1uby1yZXR1cm4 YWNyb3NzLXRoZS1ib2FyZCB3aWxsLW8tdGhlLXdpc3A\n"
235 : "\n"
236 : "@opened-at 2014-10-02 19:32:34\n");
237 :
238 1 : done:
239 1 : tor_free(contents);
240 1 : keypin_clear();
241 1 : }
242 :
243 : #undef ADD
244 : #undef LONE_RSA
245 :
246 : #define TEST(name, flags) \
247 : { #name , test_keypin_ ## name, (flags), NULL, NULL }
248 :
249 : struct testcase_t keypin_tests[] = {
250 : TEST( parse_line, 0 ),
251 : TEST( parse_file, TT_FORK ),
252 : TEST( add_entry, TT_FORK ),
253 : TEST( journal, TT_FORK ),
254 : END_OF_TESTCASES
255 : };
256 :
|