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