1#include "config.h"
2
3#include "sntptest.h"
4#include "networking.h"
5#include "ntp_stdlib.h"
6#include "unity.h"
7
8
9const char * Version = "stub unit test Version string";
10
11/* Hacks into the key database. */
12extern struct key* key_ptr;
13extern int key_cnt;
14
15
16void PrepareAuthenticationTest(int key_id,int key_len,const char* type,const void* key_seq);
17void PrepareAuthenticationTestMD5(int key_id,int key_len,const void* key_seq);
18void setUp(void);
19void tearDown(void);
20void test_TooShortLength(void);
21void test_LengthNotMultipleOfFour(void);
22void test_TooShortExtensionFieldLength(void);
23void test_UnauthenticatedPacketReject(void);
24void test_CryptoNAKPacketReject(void);
25void test_AuthenticatedPacketInvalid(void);
26void test_AuthenticatedPacketUnknownKey(void);
27void test_ServerVersionTooOld(void);
28void test_ServerVersionTooNew(void);
29void test_NonWantedMode(void);
30void test_KoDRate(void);
31void test_KoDDeny(void);
32void test_RejectUnsyncedServer(void);
33void test_RejectWrongResponseServerMode(void);
34void test_AcceptNoSentPacketBroadcastMode(void);
35void test_CorrectUnauthenticatedPacket(void);
36void test_CorrectAuthenticatedPacketMD5(void);
37void test_CorrectAuthenticatedPacketSHA1(void);
38
39/* [Bug 2998] There are some issues whith the definition of 'struct pkt'
40 * when AUTOKEY is undefined -- the formal struct is too small to hold
41 * all the extension fields that are going to be tested. We have to make
42 * sure we have the extra bytes, or the test yield undefined results due
43 * to buffer overrun.
44 */
45#ifndef AUTOKEY
46# define EXTRA_BUFSIZE 256
47#else
48# define EXTRA_BUFSIZE 0
49#endif
50
51union tpkt {
52	struct pkt p;
53	u_char     b[sizeof(struct pkt) + EXTRA_BUFSIZE];
54};
55
56static union tpkt testpkt;
57static union tpkt testspkt;
58static sockaddr_u testsock;
59bool restoreKeyDb;
60
61
62void
63PrepareAuthenticationTest(
64	int		key_id,
65	int		key_len,
66	const char *	type,
67	const void *	key_seq
68	)
69{
70	char str[25];
71	snprintf(str, 25, "%d", key_id);
72	ActivateOption("-a", str);
73
74	key_cnt = 1;
75	key_ptr = emalloc(sizeof(struct key));
76	key_ptr->next = NULL;
77	key_ptr->key_id = key_id;
78	key_ptr->key_len = key_len;
79	memcpy(key_ptr->type, "MD5", 3);
80
81	TEST_ASSERT_TRUE(key_len < sizeof(key_ptr->key_seq));
82
83	memcpy(key_ptr->key_seq, key_seq, key_ptr->key_len);
84	restoreKeyDb = true;
85}
86
87
88void
89PrepareAuthenticationTestMD5(
90	int 		key_id,
91	int 		key_len,
92	const void *	key_seq
93	)
94{
95	PrepareAuthenticationTest(key_id, key_len, "MD5", key_seq);
96}
97
98
99void
100setUp(void)
101{
102
103	sntptest();
104	restoreKeyDb = false;
105
106	/* Initialize the test packet and socket,
107	 * so they contain at least some valid data.
108	 */
109	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION,
110										MODE_SERVER);
111	testpkt.p.stratum = STRATUM_REFCLOCK;
112	memcpy(&testpkt.p.refid, "GPS\0", 4);
113
114	/* Set the origin timestamp of the received packet to the
115	 * same value as the transmit timestamp of the sent packet.
116	 */
117	l_fp tmp;
118	tmp.l_ui = 1000UL;
119	tmp.l_uf = 0UL;
120
121	HTONL_FP(&tmp, &testpkt.p.org);
122	HTONL_FP(&tmp, &testspkt.p.xmt);
123}
124
125
126void
127tearDown(void)
128{
129	if (restoreKeyDb) {
130		key_cnt = 0;
131		free(key_ptr);
132		key_ptr = NULL;
133	}
134
135	sntptest_destroy(); /* only on the final test!! if counter == 0 etc... */
136}
137
138
139void
140test_TooShortLength(void)
141{
142	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
143			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC - 1,
144				      MODE_SERVER, &testspkt.p, "UnitTest"));
145	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
146			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC - 1,
147				      MODE_BROADCAST, &testspkt.p, "UnitTest"));
148}
149
150
151void
152test_LengthNotMultipleOfFour(void)
153{
154	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
155			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC + 6,
156				      MODE_SERVER, &testspkt.p, "UnitTest"));
157	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
158			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC + 3,
159				      MODE_BROADCAST, &testspkt.p, "UnitTest"));
160}
161
162
163void
164test_TooShortExtensionFieldLength(void)
165{
166	/* [Bug 2998] We have to get around the formal specification of
167	 * the extension field if AUTOKEY is undefined. (At least CLANG
168	 * issues a warning in this case. It's just a warning, but
169	 * still...
170	 */
171	uint32_t * pe = testpkt.p.exten + 7;
172
173	/* The lower 16-bits are the length of the extension field.
174	 * This lengths must be multiples of 4 bytes, which gives
175	 * a minimum of 4 byte extension field length.
176	 */
177	*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