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