packetProcessing.c revision 338530
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
12const char * Version = "stub unit test Version string";
13
14/* Hacks into the key database. */
15extern struct key* key_ptr;
16extern int key_cnt;
17
18
19void PrepareAuthenticationTest(int key_id,int key_len,const char* type,const void* key_seq);
20void PrepareAuthenticationTestMD5(int key_id,int key_len,const void* key_seq);
21void setUp(void);
22void tearDown(void);
23void test_TooShortLength(void);
24void test_LengthNotMultipleOfFour(void);
25void test_TooShortExtensionFieldLength(void);
26void test_UnauthenticatedPacketReject(void);
27void test_CryptoNAKPacketReject(void);
28void test_AuthenticatedPacketInvalid(void);
29void test_AuthenticatedPacketUnknownKey(void);
30void test_ServerVersionTooOld(void);
31void test_ServerVersionTooNew(void);
32void test_NonWantedMode(void);
33void test_KoDRate(void);
34void test_KoDDeny(void);
35void test_RejectUnsyncedServer(void);
36void test_RejectWrongResponseServerMode(void);
37void test_AcceptNoSentPacketBroadcastMode(void);
38void test_CorrectUnauthenticatedPacket(void);
39void test_CorrectAuthenticatedPacketMD5(void);
40void test_CorrectAuthenticatedPacketSHA1(void);
41void 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
55union tpkt {
56	struct pkt p;
57	u_char     b[sizeof(struct pkt) + EXTRA_BUFSIZE];
58};
59
60static union tpkt testpkt;
61static union tpkt testspkt;
62static sockaddr_u testsock;
63bool restoreKeyDb;
64
65
66void
67PrepareAuthenticationTest(
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
92void
93PrepareAuthenticationTestMD5(
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
103void
104setUp(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
130void
131tearDown(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
143void
144test_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
155void
156test_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
167void
168test_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
195void
196test_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
211void
212test_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
226void
227test_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
252void
253test_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
276void
277test_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
294void
295test_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
312void
313test_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 */
331void
332test_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
345void
346test_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
359void
360test_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
374void
375test_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
394void
395test_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
409void
410test_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
420void
421test_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
442void
443test_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
464void
465test_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