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