packetProcessing.c revision 309008
1243791Sdim#include "config.h"
2243791Sdim
3353358Sdim#include "sntptest.h"
4353358Sdim#include "networking.h"
5353358Sdim#include "ntp_stdlib.h"
6243791Sdim#include "unity.h"
7243791Sdim
8243791Sdim
9243791Sdimconst char * Version = "stub unit test Version string";
10243791Sdim
11243791Sdim/* Hacks into the key database. */
12243791Sdimextern struct key* key_ptr;
13243791Sdimextern int key_cnt;
14243791Sdim
15243791Sdim
16243791Sdimvoid PrepareAuthenticationTest(int key_id,int key_len,const char* type,const void* key_seq);
17243791Sdimvoid PrepareAuthenticationTestMD5(int key_id,int key_len,const void* key_seq);
18243791Sdimvoid setUp(void);
19243791Sdimvoid tearDown(void);
20243791Sdimvoid test_TooShortLength(void);
21243791Sdimvoid test_LengthNotMultipleOfFour(void);
22243791Sdimvoid test_TooShortExtensionFieldLength(void);
23243791Sdimvoid test_UnauthenticatedPacketReject(void);
24243791Sdimvoid test_CryptoNAKPacketReject(void);
25243791Sdimvoid test_AuthenticatedPacketInvalid(void);
26243791Sdimvoid test_AuthenticatedPacketUnknownKey(void);
27243791Sdimvoid test_ServerVersionTooOld(void);
28327952Sdimvoid test_ServerVersionTooNew(void);
29243791Sdimvoid test_NonWantedMode(void);
30243791Sdimvoid test_KoDRate(void);
31243791Sdimvoid test_KoDDeny(void);
32243791Sdimvoid test_RejectUnsyncedServer(void);
33243791Sdimvoid test_RejectWrongResponseServerMode(void);
34243791Sdimvoid test_AcceptNoSentPacketBroadcastMode(void);
35243791Sdimvoid test_CorrectUnauthenticatedPacket(void);
36243791Sdimvoid test_CorrectAuthenticatedPacketMD5(void);
37243791Sdimvoid test_CorrectAuthenticatedPacketSHA1(void);
38243791Sdim
39243791Sdim/* [Bug 2998] There are some issues whith the definition of 'struct pkt'
40249423Sdim * when AUTOKEY is undefined -- the formal struct is too small to hold
41249423Sdim * all the extension fields that are going to be tested. We have to make
42353358Sdim * sure we have the extra bytes, or the test yield undefined results due
43243791Sdim * to buffer overrun.
44243791Sdim */
45243791Sdim#ifndef AUTOKEY
46243791Sdim# define EXTRA_BUFSIZE 256
47243791Sdim#else
48243791Sdim# define EXTRA_BUFSIZE 0
49243791Sdim#endif
50243791Sdim
51243791Sdimunion tpkt {
52243791Sdim	struct pkt p;
53243791Sdim	u_char     b[sizeof(struct pkt) + EXTRA_BUFSIZE];
54243791Sdim};
55327952Sdim
56327952Sdimstatic union tpkt testpkt;
57327952Sdimstatic union tpkt testspkt;
58327952Sdimstatic sockaddr_u testsock;
59280031Sdimbool restoreKeyDb;
60327952Sdim
61327952Sdim
62327952Sdimvoid
63327952SdimPrepareAuthenticationTest(
64280031Sdim	int		key_id,
65327952Sdim	int		key_len,
66327952Sdim	const char *	type,
67327952Sdim	const void *	key_seq
68327952Sdim	)
69280031Sdim{
70327952Sdim	char str[25];
71327952Sdim	snprintf(str, 25, "%d", key_id);
72327952Sdim	ActivateOption("-a", str);
73327952Sdim
74280031Sdim	key_cnt = 1;
75327952Sdim	key_ptr = emalloc(sizeof(struct key));
76327952Sdim	key_ptr->next = NULL;
77327952Sdim	key_ptr->key_id = key_id;
78327952Sdim	key_ptr->key_len = key_len;
79327952Sdim	memcpy(key_ptr->type, "MD5", 3);
80327952Sdim
81327952Sdim	TEST_ASSERT_TRUE(key_len < sizeof(key_ptr->key_seq));
82280031Sdim
83327952Sdim	memcpy(key_ptr->key_seq, key_seq, key_ptr->key_len);
84296417Sdim	restoreKeyDb = true;
85296417Sdim}
86243791Sdim
87276479Sdim
88327952Sdimvoid
89327952SdimPrepareAuthenticationTestMD5(
90276479Sdim	int 		key_id,
91243791Sdim	int 		key_len,
92296417Sdim	const void *	key_seq
93327952Sdim	)
94243791Sdim{
95280031Sdim	PrepareAuthenticationTest(key_id, key_len, "MD5", key_seq);
96280031Sdim}
97280031Sdim
98327952Sdim
99280031Sdimvoid
100280031SdimsetUp(void)
101280031Sdim{
102280031Sdim
103327952Sdim	sntptest();
104280031Sdim	restoreKeyDb = false;
105327952Sdim
106327952Sdim	/* Initialize the test packet and socket,
107288943Sdim	 * so they contain at least some valid data.
108276479Sdim	 */
109321369Sdim	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION,
110321369Sdim										MODE_SERVER);
111321369Sdim	testpkt.p.stratum = STRATUM_REFCLOCK;
112327952Sdim	memcpy(&testpkt.p.refid, "GPS\0", 4);
113327952Sdim
114327952Sdim	/* Set the origin timestamp of the received packet to the
115327952Sdim	 * same value as the transmit timestamp of the sent packet.
116327952Sdim	 */
117327952Sdim	l_fp tmp;
118327952Sdim	tmp.l_ui = 1000UL;
119327952Sdim	tmp.l_uf = 0UL;
120327952Sdim
121327952Sdim	HTONL_FP(&tmp, &testpkt.p.org);
122327952Sdim	HTONL_FP(&tmp, &testspkt.p.xmt);
123309124Sdim}
124309124Sdim
125243791Sdim
126296417Sdimvoid
127296417SdimtearDown(void)
128327952Sdim{
129243791Sdim	if (restoreKeyDb) {
130243791Sdim		key_cnt = 0;
131280031Sdim		free(key_ptr);
132280031Sdim		key_ptr = NULL;
133243791Sdim	}
134280031Sdim
135280031Sdim	sntptest_destroy(); /* only on the final test!! if counter == 0 etc... */
136243791Sdim}
137296417Sdim
138296417Sdim
139296417Sdimvoid
140296417Sdimtest_TooShortLength(void)
141296417Sdim{
142296417Sdim	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
143243791Sdim			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC - 1,
144280031Sdim				      MODE_SERVER, &testspkt.p, "UnitTest"));
145360784Sdim	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
146280031Sdim			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC - 1,
147327952Sdim				      MODE_BROADCAST, &testspkt.p, "UnitTest"));
148327952Sdim}
149327952Sdim
150327952Sdim
151280031Sdimvoid
152327952Sdimtest_LengthNotMultipleOfFour(void)
153280031Sdim{
154327952Sdim	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
155243791Sdim			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC + 6,
156327952Sdim				      MODE_SERVER, &testspkt.p, "UnitTest"));
157327952Sdim	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
158327952Sdim			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC + 3,
159327952Sdim				      MODE_BROADCAST, &testspkt.p, "UnitTest"));
160327952Sdim}
161327952Sdim
162327952Sdim
163327952Sdimvoid
164327952Sdimtest_TooShortExtensionFieldLength(void)
165327952Sdim{
166327952Sdim	/* [Bug 2998] We have to get around the formal specification of
167327952Sdim	 * the extension field if AUTOKEY is undefined. (At least CLANG
168327952Sdim	 * issues a warning in this case. It's just a warning, but
169327952Sdim	 * still...
170327952Sdim	 */
171327952Sdim	uint32_t * pe = testpkt.p.exten + 7;
172327952Sdim
173327952Sdim	/* The lower 16-bits are the length of the extension field.
174327952Sdim	 * This lengths must be multiples of 4 bytes, which gives
175327952Sdim	 * a minimum of 4 byte extension field length.
176327952Sdim	 */
177327952Sdim	*pe = htonl(3); /* 3 bytes is too short. */
178
179	/* We send in a pkt_len of header size + 4 byte extension
180	 * header + 24 byte MAC, this prevents the length error to
181	 * be caught at an earlier stage
182	 */
183	int pkt_len = LEN_PKT_NOMAC + 4 + 24;
184
185	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
186			  process_pkt(&testpkt.p, &testsock, pkt_len,
187				      MODE_SERVER, &testspkt.p, "UnitTest"));
188}
189
190
191void
192test_UnauthenticatedPacketReject(void)
193{
194	/* Activate authentication option */
195	ActivateOption("-a", "123");
196	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
197
198	int pkt_len = LEN_PKT_NOMAC;
199
200	/* We demand authentication, but no MAC header is present. */
201	TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL,
202			  process_pkt(&testpkt.p, &testsock, pkt_len,
203				      MODE_SERVER, &testspkt.p, "UnitTest"));
204}
205
206
207void
208test_CryptoNAKPacketReject(void)
209{
210	/* Activate authentication option */
211	ActivateOption("-a", "123");
212	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
213
214	int pkt_len = LEN_PKT_NOMAC + 4; /* + 4 byte MAC = Crypto-NAK */
215
216	TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL,
217			  process_pkt(&testpkt.p, &testsock, pkt_len,
218				      MODE_SERVER, &testspkt.p, "UnitTest"));
219}
220
221
222void
223test_AuthenticatedPacketInvalid(void)
224{
225	/* Activate authentication option */
226	PrepareAuthenticationTestMD5(50, 9, "123456789");
227	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
228
229	/* Prepare the packet. */
230	int pkt_len = LEN_PKT_NOMAC;
231
232	testpkt.p.exten[0] = htonl(50);
233	int mac_len = make_mac(&testpkt.p, pkt_len,
234			       MAX_MD5_LEN, key_ptr,
235			       &testpkt.p.exten[1]);
236
237	pkt_len += 4 + mac_len;
238
239	/* Now, alter the MAC so it becomes invalid. */
240	testpkt.p.exten[1] += 1;
241
242	TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL,
243			  process_pkt(&testpkt.p, &testsock, pkt_len,
244				      MODE_SERVER, &testspkt.p, "UnitTest"));
245}
246
247
248void
249test_AuthenticatedPacketUnknownKey(void)
250{
251	/* Activate authentication option */
252	PrepareAuthenticationTestMD5(30, 9, "123456789");
253	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
254
255	/* Prepare the packet. Note that the Key-ID expected is 30, but
256	 * the packet has a key id of 50.
257	 */
258	int pkt_len = LEN_PKT_NOMAC;
259
260	testpkt.p.exten[0] = htonl(50);
261	int mac_len = make_mac(&testpkt.p, pkt_len,
262			       MAX_MD5_LEN, key_ptr,
263			       &testpkt.p.exten[1]);
264	pkt_len += 4 + mac_len;
265
266	TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL,
267			  process_pkt(&testpkt.p, &testsock, pkt_len,
268				      MODE_SERVER, &testspkt.p, "UnitTest"));
269}
270
271
272void
273test_ServerVersionTooOld(void)
274{
275	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
276
277	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
278					      NTP_OLDVERSION - 1,
279					      MODE_CLIENT);
280	TEST_ASSERT_TRUE(PKT_VERSION(testpkt.p.li_vn_mode) < NTP_OLDVERSION);
281
282	int pkt_len = LEN_PKT_NOMAC;
283
284	TEST_ASSERT_EQUAL(SERVER_UNUSEABLE,
285			  process_pkt(&testpkt.p, &testsock, pkt_len,
286				      MODE_SERVER, &testspkt.p, "UnitTest"));
287}
288
289
290void
291test_ServerVersionTooNew(void)
292{
293	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
294
295	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
296					      NTP_VERSION + 1,
297					      MODE_CLIENT);
298	TEST_ASSERT_TRUE(PKT_VERSION(testpkt.p.li_vn_mode) > NTP_VERSION);
299
300	int pkt_len = LEN_PKT_NOMAC;
301
302	TEST_ASSERT_EQUAL(SERVER_UNUSEABLE,
303			  process_pkt(&testpkt.p, &testsock, pkt_len,
304				      MODE_SERVER, &testspkt.p, "UnitTest"));
305}
306
307
308void
309test_NonWantedMode(void)
310{
311	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
312
313	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
314					      NTP_VERSION,
315					      MODE_CLIENT);
316
317	/* The packet has a mode of MODE_CLIENT, but process_pkt expects
318	 * MODE_SERVER
319	 */
320	TEST_ASSERT_EQUAL(SERVER_UNUSEABLE,
321			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
322				      MODE_SERVER, &testspkt.p, "UnitTest"));
323}
324
325
326/* Tests bug 1597 */
327void
328test_KoDRate(void)
329{
330	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
331
332	testpkt.p.stratum = STRATUM_PKT_UNSPEC;
333	memcpy(&testpkt.p.refid, "RATE", 4);
334
335	TEST_ASSERT_EQUAL(KOD_RATE,
336			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
337				      MODE_SERVER, &testspkt.p, "UnitTest"));
338}
339
340
341void
342test_KoDDeny(void)
343{
344	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
345
346	testpkt.p.stratum = STRATUM_PKT_UNSPEC;
347	memcpy(&testpkt.p.refid, "DENY", 4);
348
349	TEST_ASSERT_EQUAL(KOD_DEMOBILIZE,
350			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
351				      MODE_SERVER, &testspkt.p, "UnitTest"));
352}
353
354
355void
356test_RejectUnsyncedServer(void)
357{
358	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
359
360	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC,
361					      NTP_VERSION,
362					      MODE_SERVER);
363
364	TEST_ASSERT_EQUAL(SERVER_UNUSEABLE,
365			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
366				      MODE_SERVER, &testspkt.p, "UnitTest"));
367}
368
369
370void
371test_RejectWrongResponseServerMode(void)
372{
373	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
374
375	l_fp tmp;
376	tmp.l_ui = 1000UL;
377	tmp.l_uf = 0UL;
378	HTONL_FP(&tmp, &testpkt.p.org);
379
380	tmp.l_ui = 2000UL;
381	tmp.l_uf = 0UL;
382	HTONL_FP(&tmp, &testspkt.p.xmt);
383
384	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
385			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
386				      MODE_SERVER, &testspkt.p, "UnitTest"));
387}
388
389
390void
391test_AcceptNoSentPacketBroadcastMode(void)
392{
393	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
394
395	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
396					      NTP_VERSION,
397					      MODE_BROADCAST);
398
399	TEST_ASSERT_EQUAL(LEN_PKT_NOMAC,
400		  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
401			      MODE_BROADCAST, NULL, "UnitTest"));
402}
403
404
405void
406test_CorrectUnauthenticatedPacket(void)
407{
408	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
409
410	TEST_ASSERT_EQUAL(LEN_PKT_NOMAC,
411			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
412				      MODE_SERVER, &testspkt.p, "UnitTest"));
413}
414
415
416void
417test_CorrectAuthenticatedPacketMD5(void)
418{
419	PrepareAuthenticationTestMD5(10, 15, "123456789abcdef");
420	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
421
422	int pkt_len = LEN_PKT_NOMAC;
423
424	/* Prepare the packet. */
425	testpkt.p.exten[0] = htonl(10);
426	int mac_len = make_mac(&testpkt.p, pkt_len,
427			       MAX_MD5_LEN, key_ptr,
428			       &testpkt.p.exten[1]);
429
430	pkt_len += 4 + mac_len;
431
432	TEST_ASSERT_EQUAL(pkt_len,
433			  process_pkt(&testpkt.p, &testsock, pkt_len,
434				      MODE_SERVER, &testspkt.p, "UnitTest"));
435}
436
437
438void
439test_CorrectAuthenticatedPacketSHA1(void)
440{
441	PrepareAuthenticationTest(20, 15, "SHA1", "abcdefghijklmno");
442	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
443
444	int pkt_len = LEN_PKT_NOMAC;
445
446	/* Prepare the packet. */
447	testpkt.p.exten[0] = htonl(20);
448	int mac_len = make_mac(&testpkt.p, pkt_len,
449			       MAX_MAC_LEN, key_ptr,
450			       &testpkt.p.exten[1]);
451
452	pkt_len += 4 + mac_len;
453
454	TEST_ASSERT_EQUAL(pkt_len,
455			  process_pkt(&testpkt.p, &testsock, pkt_len,
456				      MODE_SERVER, &testspkt.p, "UnitTest"));
457}
458