xref: /freebsd/contrib/ntp/sntp/tests/packetProcessing.c (revision d93a896ef95946b0bf1219866fcb324b78543444)
1 #include "config.h"
2 
3 #include "sntptest.h"
4 #include "networking.h"
5 #include "ntp_stdlib.h"
6 #include "unity.h"
7 
8 
9 const char * Version = "stub unit test Version string";
10 
11 /* Hacks into the key database. */
12 extern struct key* key_ptr;
13 extern int key_cnt;
14 
15 
16 void PrepareAuthenticationTest(int key_id,int key_len,const char* type,const void* key_seq);
17 void PrepareAuthenticationTestMD5(int key_id,int key_len,const void* key_seq);
18 void setUp(void);
19 void tearDown(void);
20 void test_TooShortLength(void);
21 void test_LengthNotMultipleOfFour(void);
22 void test_TooShortExtensionFieldLength(void);
23 void test_UnauthenticatedPacketReject(void);
24 void test_CryptoNAKPacketReject(void);
25 void test_AuthenticatedPacketInvalid(void);
26 void test_AuthenticatedPacketUnknownKey(void);
27 void test_ServerVersionTooOld(void);
28 void test_ServerVersionTooNew(void);
29 void test_NonWantedMode(void);
30 void test_KoDRate(void);
31 void test_KoDDeny(void);
32 void test_RejectUnsyncedServer(void);
33 void test_RejectWrongResponseServerMode(void);
34 void test_AcceptNoSentPacketBroadcastMode(void);
35 void test_CorrectUnauthenticatedPacket(void);
36 void test_CorrectAuthenticatedPacketMD5(void);
37 void 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 
51 union tpkt {
52 	struct pkt p;
53 	u_char     b[sizeof(struct pkt) + EXTRA_BUFSIZE];
54 };
55 
56 static union tpkt testpkt;
57 static union tpkt testspkt;
58 static sockaddr_u testsock;
59 bool restoreKeyDb;
60 
61 
62 void
63 PrepareAuthenticationTest(
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 
88 void
89 PrepareAuthenticationTestMD5(
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 
99 void
100 setUp(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 
126 void
127 tearDown(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 
139 void
140 test_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 
151 void
152 test_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 
163 void
164 test_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 
191 void
192 test_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 
207 void
208 test_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 
222 void
223 test_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 
248 void
249 test_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 
272 void
273 test_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 
290 void
291 test_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 
308 void
309 test_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 */
327 void
328 test_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 
341 void
342 test_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 
355 void
356 test_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 
370 void
371 test_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 
390 void
391 test_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 
405 void
406 test_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 
416 void
417 test_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 
438 void
439 test_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