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