]> git.ipfire.org Git - thirdparty/chrony.git/blame - ntp_auth.c
clientlog: add support for KoD rate limiting
[thirdparty/chrony.git] / ntp_auth.c
CommitLineData
ca28dbd2
ML
1/*
2 chronyd/chronyc - Programs for keeping computer clocks accurate.
3
4 **********************************************************************
3916c336 5 * Copyright (C) Miroslav Lichvar 2019-2020
ca28dbd2
ML
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 *
20 **********************************************************************
21
22 =======================================================================
23
24 NTP authentication
25 */
26
27#include "config.h"
28
29#include "sysincl.h"
30
31#include "keys.h"
32#include "logging.h"
33#include "memory.h"
34#include "ntp_auth.h"
35#include "ntp_signd.h"
c4150872
ML
36#include "nts_ntp.h"
37#include "nts_ntp_client.h"
38#include "nts_ntp_server.h"
ca28dbd2
ML
39#include "srcparams.h"
40#include "util.h"
41
42/* Structure to hold authentication configuration and state */
43
44struct NAU_Instance_Record {
45 NTP_AuthMode mode; /* Authentication mode of NTP packets */
46 uint32_t key_id; /* Identifier of a symmetric key */
c4150872 47 NNC_Instance nts; /* Client NTS state */
ca28dbd2
ML
48};
49
50/* ================================================== */
51
52static int
53generate_symmetric_auth(uint32_t key_id, NTP_Packet *packet, NTP_PacketInfo *info)
54{
55 int auth_len, max_auth_len;
56
0e51552d
ML
57 if (info->length + NTP_MIN_MAC_LENGTH > sizeof (*packet)) {
58 DEBUG_LOG("Packet too long");
59 return 0;
60 }
61
ca28dbd2
ML
62 /* Truncate long MACs in NTPv4 packets to allow deterministic parsing
63 of extension fields (RFC 7822) */
64 max_auth_len = (info->version == 4 ? NTP_MAX_V4_MAC_LENGTH : NTP_MAX_MAC_LENGTH) - 4;
0e51552d 65 max_auth_len = MIN(max_auth_len, sizeof (*packet) - info->length - 4);
ca28dbd2 66
d93aa10b 67 auth_len = KEY_GenerateAuth(key_id, packet, info->length,
ca28dbd2 68 (unsigned char *)packet + info->length + 4, max_auth_len);
0e51552d 69 if (auth_len < NTP_MIN_MAC_LENGTH - 4) {
ca28dbd2
ML
70 DEBUG_LOG("Could not generate auth data with key %"PRIu32, key_id);
71 return 0;
72 }
73
74 *(uint32_t *)((unsigned char *)packet + info->length) = htonl(key_id);
0e51552d
ML
75
76 info->auth.mac.start = info->length;
77 info->auth.mac.length = 4 + auth_len;
78 info->auth.mac.key_id = key_id;
79 info->length += info->auth.mac.length;
ca28dbd2
ML
80
81 return 1;
82}
83
84/* ================================================== */
85
86static int
87check_symmetric_auth(NTP_Packet *packet, NTP_PacketInfo *info)
88{
89 int trunc_len;
90
91 if (info->auth.mac.length < NTP_MIN_MAC_LENGTH)
92 return 0;
93
94 trunc_len = info->version == 4 && info->auth.mac.length <= NTP_MAX_V4_MAC_LENGTH ?
95 NTP_MAX_V4_MAC_LENGTH : NTP_MAX_MAC_LENGTH;
96
d93aa10b 97 if (!KEY_CheckAuth(info->auth.mac.key_id, packet, info->auth.mac.start,
ca28dbd2
ML
98 (unsigned char *)packet + info->auth.mac.start + 4,
99 info->auth.mac.length - 4, trunc_len - 4))
100 return 0;
101
102 return 1;
103}
104
105/* ================================================== */
106
ca28dbd2
ML
107static NAU_Instance
108create_instance(NTP_AuthMode mode)
109{
110 NAU_Instance instance;
111
112 instance = MallocNew(struct NAU_Instance_Record);
113 instance->mode = mode;
114 instance->key_id = INACTIVE_AUTHKEY;
c4150872 115 instance->nts = NULL;
ca28dbd2
ML
116
117 assert(sizeof (instance->key_id) == 4);
118
119 return instance;
120}
121
122/* ================================================== */
123
124NAU_Instance
125NAU_CreateNoneInstance(void)
126{
46cac4e2 127 return create_instance(NTP_AUTH_NONE);
ca28dbd2
ML
128}
129
130/* ================================================== */
131
132NAU_Instance
133NAU_CreateSymmetricInstance(uint32_t key_id)
134{
46cac4e2 135 NAU_Instance instance = create_instance(NTP_AUTH_SYMMETRIC);
ca28dbd2
ML
136
137 instance->key_id = key_id;
138
139 if (!KEY_KeyKnown(key_id))
140 LOG(LOGS_WARN, "Key %"PRIu32" is %s", key_id, "missing");
141 else if (!KEY_CheckKeyLength(key_id))
142 LOG(LOGS_WARN, "Key %"PRIu32" is %s", key_id, "too short");
143
144 return instance;
145}
146
147/* ================================================== */
148
c4150872 149NAU_Instance
6615bb1b
ML
150NAU_CreateNtsInstance(IPSockAddr *nts_address, const char *name, uint32_t cert_set,
151 uint16_t ntp_port)
c4150872
ML
152{
153 NAU_Instance instance = create_instance(NTP_AUTH_NTS);
154
6615bb1b 155 instance->nts = NNC_CreateInstance(nts_address, name, cert_set, ntp_port);
c4150872
ML
156
157 return instance;
158}
159
160/* ================================================== */
161
ca28dbd2
ML
162void
163NAU_DestroyInstance(NAU_Instance instance)
164{
59ad433b 165 if (instance->mode == NTP_AUTH_NTS)
c4150872 166 NNC_DestroyInstance(instance->nts);
ca28dbd2
ML
167 Free(instance);
168}
169
170/* ================================================== */
171
172int
173NAU_IsAuthEnabled(NAU_Instance instance)
174{
46cac4e2 175 return instance->mode != NTP_AUTH_NONE;
ca28dbd2
ML
176}
177
178/* ================================================== */
179
180int
181NAU_GetSuggestedNtpVersion(NAU_Instance instance)
182{
183 /* If the MAC in NTPv4 packets would be truncated, prefer NTPv3 for
184 compatibility with older chronyd servers */
46cac4e2 185 if (instance->mode == NTP_AUTH_SYMMETRIC &&
ca28dbd2
ML
186 KEY_GetAuthLength(instance->key_id) + sizeof (instance->key_id) > NTP_MAX_V4_MAC_LENGTH)
187 return 3;
188
189 return NTP_VERSION;
190}
191
192/* ================================================== */
193
194int
195NAU_PrepareRequestAuth(NAU_Instance instance)
196{
197 switch (instance->mode) {
c4150872
ML
198 case NTP_AUTH_NTS:
199 if (!NNC_PrepareForAuth(instance->nts))
200 return 0;
201 break;
ca28dbd2
ML
202 default:
203 break;
204 }
205
206 return 1;
207}
208
209/* ================================================== */
210
ca28dbd2
ML
211int
212NAU_GenerateRequestAuth(NAU_Instance instance, NTP_Packet *request, NTP_PacketInfo *info)
213{
214 switch (instance->mode) {
46cac4e2 215 case NTP_AUTH_NONE:
ca28dbd2 216 break;
46cac4e2 217 case NTP_AUTH_SYMMETRIC:
ca28dbd2
ML
218 if (!generate_symmetric_auth(instance->key_id, request, info))
219 return 0;
220 break;
c4150872
ML
221 case NTP_AUTH_NTS:
222 if (!NNC_GenerateRequestAuth(instance->nts, request, info))
223 return 0;
224 break;
ca28dbd2
ML
225 default:
226 assert(0);
227 }
228
0e51552d
ML
229 info->auth.mode = instance->mode;
230
ca28dbd2
ML
231 return 1;
232}
233
234/* ================================================== */
235
236int
aca1daf7 237NAU_CheckRequestAuth(NTP_Packet *request, NTP_PacketInfo *info, uint32_t *kod)
ca28dbd2 238{
aca1daf7
ML
239 *kod = 0;
240
ca28dbd2 241 switch (info->auth.mode) {
46cac4e2 242 case NTP_AUTH_NONE:
ca28dbd2 243 break;
46cac4e2 244 case NTP_AUTH_SYMMETRIC:
ca28dbd2
ML
245 if (!check_symmetric_auth(request, info))
246 return 0;
247 break;
46cac4e2 248 case NTP_AUTH_MSSNTP:
ca28dbd2
ML
249 /* MS-SNTP requests are not authenticated */
250 break;
0e51552d
ML
251 case NTP_AUTH_MSSNTP_EXT:
252 /* Not supported yet */
253 return 0;
c4150872
ML
254 case NTP_AUTH_NTS:
255 if (!NNS_CheckRequestAuth(request, info, kod))
256 return 0;
257 break;
ca28dbd2
ML
258 default:
259 return 0;
260 }
261
262 return 1;
263}
264
265/* ================================================== */
ca28dbd2
ML
266
267int
268NAU_GenerateResponseAuth(NTP_Packet *request, NTP_PacketInfo *request_info,
269 NTP_Packet *response, NTP_PacketInfo *response_info,
aca1daf7
ML
270 NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr,
271 uint32_t kod)
ca28dbd2
ML
272{
273 switch (request_info->auth.mode) {
46cac4e2 274 case NTP_AUTH_NONE:
ca28dbd2 275 break;
46cac4e2 276 case NTP_AUTH_SYMMETRIC:
ca28dbd2
ML
277 if (!generate_symmetric_auth(request_info->auth.mac.key_id, response, response_info))
278 return 0;
279 break;
46cac4e2 280 case NTP_AUTH_MSSNTP:
ca28dbd2
ML
281 /* Sign the packet asynchronously by ntp_signd */
282 if (!NSD_SignAndSendPacket(request_info->auth.mac.key_id, response, response_info,
283 remote_addr, local_addr))
284 return 0;
285 /* Don't send the original packet */
286 return 0;
c4150872
ML
287 case NTP_AUTH_NTS:
288 if (!NNS_GenerateResponseAuth(request, request_info, response, response_info, kod))
289 return 0;
290 break;
ca28dbd2
ML
291 default:
292 DEBUG_LOG("Could not authenticate response auth_mode=%d", (int)request_info->auth.mode);
293 return 0;
294 }
295
0e51552d
ML
296 response_info->auth.mode = request_info->auth.mode;
297
ca28dbd2
ML
298 return 1;
299}
300
301/* ================================================== */
302
303int
304NAU_CheckResponseAuth(NAU_Instance instance, NTP_Packet *response, NTP_PacketInfo *info)
305{
ca28dbd2
ML
306 /* The authentication must match the expected mode */
307 if (info->auth.mode != instance->mode)
308 return 0;
309
310 switch (info->auth.mode) {
46cac4e2 311 case NTP_AUTH_NONE:
ca28dbd2 312 break;
46cac4e2 313 case NTP_AUTH_SYMMETRIC:
ca28dbd2
ML
314 /* Check if it is authenticated with the specified key */
315 if (info->auth.mac.key_id != instance->key_id)
316 return 0;
317 /* and that the MAC is valid */
318 if (!check_symmetric_auth(response, info))
319 return 0;
320 break;
c4150872
ML
321 case NTP_AUTH_NTS:
322 if (!NNC_CheckResponseAuth(instance->nts, response, info))
323 return 0;
324 break;
ca28dbd2
ML
325 default:
326 return 0;
327 }
328
329 return 1;
330}
86d29221
ML
331
332/* ================================================== */
333
334void
335NAU_ChangeAddress(NAU_Instance instance, IPAddr *address)
336{
337 switch (instance->mode) {
338 case NTP_AUTH_NONE:
339 case NTP_AUTH_SYMMETRIC:
340 break;
c4150872
ML
341 case NTP_AUTH_NTS:
342 NNC_ChangeAddress(instance->nts, address);
343 break;
86d29221
ML
344 default:
345 assert(0);
346 }
347}
d690faeb
ML
348
349/* ================================================== */
350
351void
352NAU_DumpData(NAU_Instance instance)
353{
354 switch (instance->mode) {
355 case NTP_AUTH_NTS:
356 NNC_DumpData(instance->nts);
357 break;
358 default:
359 break;
360 }
361}
79c7384e
ML
362
363/* ================================================== */
364
365void
366NAU_GetReport(NAU_Instance instance, RPT_AuthReport *report)
367{
368 memset(report, 0, sizeof (*report));
369
370 report->mode = instance->mode;
371 report->last_ke_ago = -1;
372
373 switch (instance->mode) {
374 case NTP_AUTH_NONE:
375 break;
376 case NTP_AUTH_SYMMETRIC:
377 report->key_id = instance->key_id;
378 KEY_GetKeyInfo(instance->key_id, &report->key_type, &report->key_length);
379 break;
380 case NTP_AUTH_NTS:
381 NNC_GetReport(instance->nts, report);
382 break;
383 default:
384 assert(0);
385 }
386}