1 #include "config.h"
2 
3 #include "sntptest.h"
4 #include "networking.h"
5 #include "ntp_stdlib.h"
6 #include "unity.h"
7 
8 #define CMAC		"AES128CMAC"
9 #define CMAC_LENGTH	16
10 
11 
12 /* Hacks into the key database. */
13 extern struct key* key_ptr;
14 extern int key_cnt;
15 
16 
17 void PrepareAuthenticationTest(int key_id,int key_len,const char* type,const void* key_seq);
18 void PrepareAuthenticationTestMD5(int key_id,int key_len,const void* key_seq);
19 void setUp(void);
20 void tearDown(void);
21 void test_TooShortLength(void);
22 void test_LengthNotMultipleOfFour(void);
23 void test_TooShortExtensionFieldLength(void);
24 void test_UnauthenticatedPacketReject(void);
25 void test_CryptoNAKPacketReject(void);
26 void test_AuthenticatedPacketInvalid(void);
27 void test_AuthenticatedPacketUnknownKey(void);
28 void test_ServerVersionTooOld(void);
29 void test_ServerVersionTooNew(void);
30 void test_NonWantedMode(void);
31 void test_KoDRate(void);
32 void test_KoDDeny(void);
33 void test_RejectUnsyncedServer(void);
34 void test_RejectWrongResponseServerMode(void);
35 void test_AcceptNoSentPacketBroadcastMode(void);
36 void test_CorrectUnauthenticatedPacket(void);
37 void test_CorrectAuthenticatedPacketMD5(void);
38 void test_CorrectAuthenticatedPacketSHA1(void);
39 void test_CorrectAuthenticatedPacketCMAC(void);
40 
41 /* [Bug 2998] There are some issues whith the definition of 'struct pkt'
42  * when AUTOKEY is undefined -- the formal struct is too small to hold
43  * all the extension fields that are going to be tested. We have to make
44  * sure we have the extra bytes, or the test yield undefined results due
45  * to buffer overrun.
46  */
47 #ifndef AUTOKEY
48 # define EXTRA_BUFSIZE 256
49 #else
50 # define EXTRA_BUFSIZE 0
51 #endif
52 
53 union tpkt {
54 	struct pkt p;
55 	u_char     b[sizeof(struct pkt) + EXTRA_BUFSIZE];
56 };
57 
58 static union tpkt testpkt;
59 static union tpkt testspkt;
60 static sockaddr_u testsock;
61 bool restoreKeyDb;
62 
63 
64 void
65 PrepareAuthenticationTest(
66 	int		key_id,
67 	int		key_len,
68 	const char *	type,
69 	const void *	key_seq
70 	)
71 {
72 	char str[25];
73 	snprintf(str, 25, "%d", key_id);
74 	ActivateOption("-a", str);
75 
76 	key_cnt = 1;
77 	key_ptr = emalloc(sizeof(struct key));
78 	key_ptr->next = NULL;
79 	key_ptr->key_id = key_id;
80 	key_ptr->key_len = key_len;
81 	memcpy(key_ptr->typen, type, strlen(type) + 1);
82 
83 	TEST_ASSERT_TRUE(key_len < sizeof(key_ptr->key_seq));
84 
85 	memcpy(key_ptr->key_seq, key_seq, key_ptr->key_len);
86 	restoreKeyDb = true;
87 }
88 
89 
90 void
91 PrepareAuthenticationTestMD5(
92 	int 		key_id,
93 	int 		key_len,
94 	const void *	key_seq
95 	)
96 {
97 	PrepareAuthenticationTest(key_id, key_len, "MD5", key_seq);
98 }
99 
100 
101 void
102 setUp(void)
103 {
104 
105 	sntptest();
106 	restoreKeyDb = false;
107 
108 	/* Initialize the test packet and socket,
109 	 * so they contain at least some valid data.
110 	 */
111 	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION,
112 										MODE_SERVER);
113 	testpkt.p.stratum = STRATUM_REFCLOCK;
114 	memcpy(&testpkt.p.refid, "GPS\0", 4);
115 
116 	/* Set the origin timestamp of the received packet to the
117 	 * same value as the transmit timestamp of the sent packet.
118 	 */
119 	l_fp tmp;
120 	tmp.l_ui = 1000UL;
121 	tmp.l_uf = 0UL;
122 
123 	HTONL_FP(&tmp, &testpkt.p.org);
124 	HTONL_FP(&tmp, &testspkt.p.xmt);
125 }
126 
127 
128 void
129 tearDown(void)
130 {
131 	if (restoreKeyDb) {
132 		key_cnt = 0;
133 		free(key_ptr);
134 		key_ptr = NULL;
135 	}
136 
137 	sntptest_destroy(); /* only on the final test!! if counter == 0 etc... */
138 }
139 
140 
141 void
142 test_TooShortLength(void)
143 {
144 	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
145 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC - 1,
146 				      MODE_SERVER, &testspkt.p, "UnitTest"));
147 	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
148 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC - 1,
149 				      MODE_BROADCAST, &testspkt.p, "UnitTest"));
150 }
151 
152 
153 void
154 test_LengthNotMultipleOfFour(void)
155 {
156 	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
157 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC + 6,
158 				      MODE_SERVER, &testspkt.p, "UnitTest"));
159 	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
160 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC + 3,
161 				      MODE_BROADCAST, &testspkt.p, "UnitTest"));
162 }
163 
164 
165 void
166 test_TooShortExtensionFieldLength(void)
167 {
168 	/* [Bug 2998] We have to get around the formal specification of
169 	 * the extension field if AUTOKEY is undefined. (At least CLANG
170 	 * issues a warning in this case. It's just a warning, but
171 	 * still...
172 	 */
173 	uint32_t * pe = testpkt.p.exten + 7;
174 
175 	/* The lower 16-bits are the length of the extension field.
176 	 * This lengths must be multiples of 4 bytes, which gives
177 	 * a minimum of 4 byte extension field length.
178 	 */
179 	*pe = htonl(3); /* 3 bytes is too short. */
180 
181 	/* We send in a pkt_len of header size + 4 byte extension
182 	 * header + 24 byte MAC, this prevents the length error to
183 	 * be caught at an earlier stage
184 	 */
185 	int pkt_len = LEN_PKT_NOMAC + 4 + 24;
186 
187 	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
188 			  process_pkt(&testpkt.p, &testsock, pkt_len,
189 				      MODE_SERVER, &testspkt.p, "UnitTest"));
190 }
191 
192 
193 void
194 test_UnauthenticatedPacketReject(void)
195 {
196 	/* Activate authentication option */
197 	ActivateOption("-a", "123");
198 	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
199 
200 	int pkt_len = LEN_PKT_NOMAC;
201 
202 	/* We demand authentication, but no MAC header is present. */
203 	TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL,
204 			  process_pkt(&testpkt.p, &testsock, pkt_len,
205 				      MODE_SERVER, &testspkt.p, "UnitTest"));
206 }
207 
208 
209 void
210 test_CryptoNAKPacketReject(void)
211 {
212 	/* Activate authentication option */
213 	ActivateOption("-a", "123");
214 	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
215 
216 	int pkt_len = LEN_PKT_NOMAC + 4; /* + 4 byte MAC = Crypto-NAK */
217 
218 	TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL,
219 			  process_pkt(&testpkt.p, &testsock, pkt_len,
220 				      MODE_SERVER, &testspkt.p, "UnitTest"));
221 }
222 
223 
224 void
225 test_AuthenticatedPacketInvalid(void)
226 {
227 	/* Activate authentication option */
228 	PrepareAuthenticationTestMD5(50, 9, "123456789");
229 	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
230 
231 	/* Prepare the packet. */
232 	int pkt_len = LEN_PKT_NOMAC;
233 
234 	testpkt.p.exten[0] = htonl(50);
235 	int mac_len = make_mac(&testpkt.p, pkt_len,
236 			       MAX_MD5_LEN - KEY_MAC_LEN, key_ptr,
237 			       &testpkt.p.exten[1]);
238 
239 	pkt_len += 4 + mac_len;
240 
241 	/* Now, alter the MAC so it becomes invalid. */
242 	testpkt.p.exten[1] += 1;
243 
244 	TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL,
245 			  process_pkt(&testpkt.p, &testsock, pkt_len,
246 				      MODE_SERVER, &testspkt.p, "UnitTest"));
247 }
248 
249 
250 void
251 test_AuthenticatedPacketUnknownKey(void)
252 {
253 	/* Activate authentication option */
254 	PrepareAuthenticationTestMD5(30, 9, "123456789");
255 	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
256 
257 	/* Prepare the packet. Note that the Key-ID expected is 30, but
258 	 * the packet has a key id of 50.
259 	 */
260 	int pkt_len = LEN_PKT_NOMAC;
261 
262 	testpkt.p.exten[0] = htonl(50);
263 	int mac_len = make_mac(&testpkt.p, pkt_len,
264 			       MAX_MD5_LEN - KEY_MAC_LEN, key_ptr,
265 			       &testpkt.p.exten[1]);
266 	pkt_len += KEY_MAC_LEN + mac_len;
267 
268 	TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL,
269 			  process_pkt(&testpkt.p, &testsock, pkt_len,
270 				      MODE_SERVER, &testspkt.p, "UnitTest"));
271 }
272 
273 
274 void
275 test_ServerVersionTooOld(void)
276 {
277 	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
278 
279 	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
280 					      NTP_OLDVERSION - 1,
281 					      MODE_CLIENT);
282 	TEST_ASSERT_TRUE(PKT_VERSION(testpkt.p.li_vn_mode) < NTP_OLDVERSION);
283 
284 	int pkt_len = LEN_PKT_NOMAC;
285 
286 	TEST_ASSERT_EQUAL(SERVER_UNUSEABLE,
287 			  process_pkt(&testpkt.p, &testsock, pkt_len,
288 				      MODE_SERVER, &testspkt.p, "UnitTest"));
289 }
290 
291 
292 void
293 test_ServerVersionTooNew(void)
294 {
295 	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
296 
297 	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
298 					      NTP_VERSION + 1,
299 					      MODE_CLIENT);
300 	TEST_ASSERT_TRUE(PKT_VERSION(testpkt.p.li_vn_mode) > NTP_VERSION);
301 
302 	int pkt_len = LEN_PKT_NOMAC;
303 
304 	TEST_ASSERT_EQUAL(SERVER_UNUSEABLE,
305 			  process_pkt(&testpkt.p, &testsock, pkt_len,
306 				      MODE_SERVER, &testspkt.p, "UnitTest"));
307 }
308 
309 
310 void
311 test_NonWantedMode(void)
312 {
313 	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
314 
315 	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
316 					      NTP_VERSION,
317 					      MODE_CLIENT);
318 
319 	/* The packet has a mode of MODE_CLIENT, but process_pkt expects
320 	 * MODE_SERVER
321 	 */
322 	TEST_ASSERT_EQUAL(SERVER_UNUSEABLE,
323 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
324 				      MODE_SERVER, &testspkt.p, "UnitTest"));
325 }
326 
327 
328 /* Tests bug 1597 */
329 void
330 test_KoDRate(void)
331 {
332 	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
333 
334 	testpkt.p.stratum = STRATUM_PKT_UNSPEC;
335 	memcpy(&testpkt.p.refid, "RATE", 4);
336 
337 	TEST_ASSERT_EQUAL(KOD_RATE,
338 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
339 				      MODE_SERVER, &testspkt.p, "UnitTest"));
340 }
341 
342 
343 void
344 test_KoDDeny(void)
345 {
346 	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
347 
348 	testpkt.p.stratum = STRATUM_PKT_UNSPEC;
349 	memcpy(&testpkt.p.refid, "DENY", 4);
350 
351 	TEST_ASSERT_EQUAL(KOD_DEMOBILIZE,
352 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
353 				      MODE_SERVER, &testspkt.p, "UnitTest"));
354 }
355 
356 
357 void
358 test_RejectUnsyncedServer(void)
359 {
360 	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
361 
362 	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC,
363 					      NTP_VERSION,
364 					      MODE_SERVER);
365 
366 	TEST_ASSERT_EQUAL(SERVER_UNUSEABLE,
367 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
368 				      MODE_SERVER, &testspkt.p, "UnitTest"));
369 }
370 
371 
372 void
373 test_RejectWrongResponseServerMode(void)
374 {
375 	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
376 
377 	l_fp tmp;
378 	tmp.l_ui = 1000UL;
379 	tmp.l_uf = 0UL;
380 	HTONL_FP(&tmp, &testpkt.p.org);
381 
382 	tmp.l_ui = 2000UL;
383 	tmp.l_uf = 0UL;
384 	HTONL_FP(&tmp, &testspkt.p.xmt);
385 
386 	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
387 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
388 				      MODE_SERVER, &testspkt.p, "UnitTest"));
389 }
390 
391 
392 void
393 test_AcceptNoSentPacketBroadcastMode(void)
394 {
395 	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
396 
397 	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
398 					      NTP_VERSION,
399 					      MODE_BROADCAST);
400 
401 	TEST_ASSERT_EQUAL(LEN_PKT_NOMAC,
402 		  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
403 			      MODE_BROADCAST, NULL, "UnitTest"));
404 }
405 
406 
407 void
408 test_CorrectUnauthenticatedPacket(void)
409 {
410 	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
411 
412 	TEST_ASSERT_EQUAL(LEN_PKT_NOMAC,
413 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
414 				      MODE_SERVER, &testspkt.p, "UnitTest"));
415 }
416 
417 
418 void
419 test_CorrectAuthenticatedPacketMD5(void)
420 {
421 	PrepareAuthenticationTestMD5(10, 15, "123456789abcdef");
422 	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
423 
424 	int pkt_len = LEN_PKT_NOMAC;
425 
426 	/* Prepare the packet. */
427 	testpkt.p.exten[0] = htonl(10);
428 	int mac_len = make_mac(&testpkt.p, pkt_len,
429 			       MAX_MD5_LEN - KEY_MAC_LEN, key_ptr,
430 			       &testpkt.p.exten[1]);
431 
432 	pkt_len += KEY_MAC_LEN + mac_len;
433 
434 	TEST_ASSERT_EQUAL(pkt_len,
435 			  process_pkt(&testpkt.p, &testsock, pkt_len,
436 				      MODE_SERVER, &testspkt.p, "UnitTest"));
437 }
438 
439 
440 void
441 test_CorrectAuthenticatedPacketSHA1(void)
442 {
443 	PrepareAuthenticationTest(20, 15, "SHA1", "abcdefghijklmno");
444 	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
445 
446 	int pkt_len = LEN_PKT_NOMAC;
447 
448 	/* Prepare the packet. */
449 	testpkt.p.exten[0] = htonl(20);
450 	int mac_len = make_mac(&testpkt.p, pkt_len,
451 			       MAX_MDG_LEN, key_ptr,
452 			       &testpkt.p.exten[1]);
453 
454 	pkt_len += KEY_MAC_LEN + mac_len;
455 
456 	TEST_ASSERT_EQUAL(pkt_len,
457 			  process_pkt(&testpkt.p, &testsock, pkt_len,
458 				      MODE_SERVER, &testspkt.p, "UnitTest"));
459 }
460 
461 
462 void
463 test_CorrectAuthenticatedPacketCMAC(void)
464 {
465 #if defined(OPENSSL) && defined(ENABLE_CMAC)
466 
467 	PrepareAuthenticationTest(30, CMAC_LENGTH, CMAC, "abcdefghijklmnop");
468 	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
469 
470 	int pkt_len = LEN_PKT_NOMAC;
471 
472 	/* Prepare the packet. */
473 	testpkt.p.exten[0] = htonl(30);
474 	int mac_len = make_mac(&testpkt.p, pkt_len,
475 			       MAX_MAC_LEN, key_ptr,
476 			       &testpkt.p.exten[1]);
477 
478 	pkt_len += 4 + mac_len;
479 
480 	TEST_ASSERT_EQUAL(pkt_len,
481 			  process_pkt(&testpkt.p, &testsock, pkt_len,
482 				      MODE_SERVER, &testspkt.p, "UnitTest"));
483 
484 #else
485 
486 	TEST_IGNORE_MESSAGE("OpenSSL CMAC not used, skipping...");
487 
488 #endif	/* OPENSSL */
489 }
490 
491