1 /*
2 **********************************************************************
3 * Copyright (C) Miroslav Lichvar 2020
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 **********************************************************************
19 */
20
21 #include <config.h>
22 #include "test.h"
23
24 #ifdef FEAT_NTS
25
26 #include <local.h>
27 #include <sched.h>
28
29 #include <nts_ntp_server.c>
30
31 static void
prepare_request(NTP_Packet * packet,NTP_PacketInfo * info,int valid,int nak)32 prepare_request(NTP_Packet *packet, NTP_PacketInfo *info, int valid, int nak)
33 {
34 unsigned char uniq_id[NTS_MIN_UNIQ_ID_LENGTH], nonce[NTS_MIN_UNPADDED_NONCE_LENGTH];
35 SIV_Instance siv;
36 NKE_Context context;
37 NKE_Cookie cookie;
38 int i, index, cookie_start, auth_start;
39
40 context.algorithm = SERVER_SIV;
41 context.c2s.length = SIV_GetKeyLength(context.algorithm);
42 UTI_GetRandomBytes(&context.c2s.key, context.c2s.length);
43 context.s2c.length = SIV_GetKeyLength(context.algorithm);
44 UTI_GetRandomBytes(&context.s2c.key, context.s2c.length);
45
46 TEST_CHECK(NKS_GenerateCookie(&context, &cookie));
47
48 UTI_GetRandomBytes(uniq_id, sizeof (uniq_id));
49 UTI_GetRandomBytes(nonce, sizeof (nonce));
50
51 memset(packet, 0, sizeof (*packet));
52 packet->lvm = NTP_LVM(0, 4, MODE_CLIENT);
53 memset(info, 0, sizeof (*info));
54 info->version = 4;
55 info->mode = MODE_CLIENT;
56 info->length = NTP_HEADER_LENGTH;
57
58 if (valid)
59 index = -1;
60 else
61 index = random() % 3;
62
63 DEBUG_LOG("valid=%d nak=%d index=%d", valid, nak, index);
64
65 if (index != 0)
66 TEST_CHECK(NEF_AddField(packet, info, NTP_EF_NTS_UNIQUE_IDENTIFIER,
67 uniq_id, sizeof (uniq_id)));
68
69 cookie_start = info->length;
70
71 if (index != 1)
72 TEST_CHECK(NEF_AddField(packet, info, NTP_EF_NTS_COOKIE,
73 cookie.cookie, cookie.length));
74
75 for (i = random() % 4; i > 0; i--)
76 TEST_CHECK(NEF_AddField(packet, info, NTP_EF_NTS_COOKIE_PLACEHOLDER,
77 cookie.cookie, cookie.length));
78
79 auth_start = info->length;
80
81 if (index != 2) {
82 siv = SIV_CreateInstance(context.algorithm);
83 TEST_CHECK(SIV_SetKey(siv, context.c2s.key, context.c2s.length));
84 TEST_CHECK(NNA_GenerateAuthEF(packet, info, siv, nonce, sizeof (nonce),
85 (const unsigned char *)"", 0, 0));
86 SIV_DestroyInstance(siv);
87 }
88
89 if (nak)
90 ((unsigned char *)packet)[(index == 2 ? cookie_start :
91 (index == 1 ? auth_start :
92 (random() % 2 ? cookie_start : auth_start))) +
93 4 + random() % 16]++;
94 }
95
96 static void
init_response(NTP_Packet * packet,NTP_PacketInfo * info)97 init_response(NTP_Packet *packet, NTP_PacketInfo *info)
98 {
99 memset(packet, 0, sizeof (*packet));
100 packet->lvm = NTP_LVM(0, 4, MODE_SERVER);
101 memset(info, 0, sizeof (*info));
102 info->version = 4;
103 info->mode = MODE_SERVER;
104 info->length = NTP_HEADER_LENGTH;
105 }
106
107 void
test_unit(void)108 test_unit(void)
109 {
110 NTP_PacketInfo req_info, res_info;
111 NTP_Packet request, response;
112 int i, valid, nak;
113 uint32_t kod;
114
115 char conf[][100] = {
116 "ntsport 0",
117 "ntsprocesses 0",
118 "ntsserverkey nts_ke.key",
119 "ntsservercert nts_ke.crt",
120 };
121
122 CNF_Initialise(0, 0);
123 for (i = 0; i < sizeof conf / sizeof conf[0]; i++)
124 CNF_ParseLine(NULL, i + 1, conf[i]);
125
126 LCL_Initialise();
127 TST_RegisterDummyDrivers();
128 SCH_Initialise();
129 NKS_PreInitialise(0, 0, 0);
130 NKS_Initialise();
131 NNS_Initialise();
132
133 for (i = 0; i < 50000; i++) {
134 valid = random() % 2;
135 nak = random() % 2;
136 prepare_request(&request, &req_info, valid, nak);
137
138 TEST_CHECK(NNS_CheckRequestAuth(&request, &req_info, &kod) == (valid && !nak));
139
140 if (valid && !nak) {
141 TEST_CHECK(kod == 0);
142 TEST_CHECK(server->num_cookies > 0);
143
144 init_response(&response, &res_info);
145 TEST_CHECK(NNS_GenerateResponseAuth(&request, &req_info, &response, &res_info, kod));
146
147 TEST_CHECK(res_info.ext_fields == 2);
148 TEST_CHECK(server->num_cookies == 0);
149 } else if (valid && nak) {
150 TEST_CHECK(kod == NTP_KOD_NTS_NAK);
151 TEST_CHECK(server->num_cookies == 0);
152
153 init_response(&response, &res_info);
154 TEST_CHECK(NNS_GenerateResponseAuth(&request, &req_info, &response, &res_info, kod));
155
156 TEST_CHECK(res_info.ext_fields == 1);
157 TEST_CHECK(server->num_cookies == 0);
158 } else {
159 TEST_CHECK(kod == 0);
160 TEST_CHECK(server->num_cookies == 0);
161 }
162 }
163
164 NNS_Finalise();
165 NKS_Finalise();
166 SCH_Finalise();
167 LCL_Finalise();
168 CNF_Finalise();
169 }
170 #else
171 void
test_unit(void)172 test_unit(void)
173 {
174 TEST_REQUIRE(0);
175 }
176 #endif
177