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