Coverage Report

Created: 2025-01-09 06:26

/src/ntpsec/ntpd/nts_client.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * nts_client.c - Network Time Security (NTS) client side support
3
 * Copyright the NTPsec project contributors
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 *
6
 * Section references are to
7
 * https://tools.ietf.org/html/rfc8915
8
 *
9
 */
10
#include "config.h"
11
12
#include <ctype.h>
13
#include <sys/types.h>
14
#include <sys/socket.h>
15
#include <sys/stat.h>
16
#include <unistd.h>
17
#include <fcntl.h>
18
19
#ifdef HAVE_RES_INIT
20
#include <netinet/in.h>
21
#include <arpa/nameser.h>
22
#include <resolv.h>
23
#endif
24
25
#include <openssl/ssl.h>
26
#include <openssl/x509.h>
27
#include <openssl/x509v3.h>
28
29
#include "ntp_types.h"
30
#include "ntpd.h"
31
#include "nts.h"
32
#include "nts2.h"
33
#include "ntp_dns.h"
34
#include "ntp_stdlib.h"
35
#include "timespecops.h"
36
37
SSL_CTX* make_ssl_client_ctx(const char *filename);
38
int open_TCP_socket(struct peer *peer, const char *hostname);
39
struct addrinfo * find_best_addr(struct addrinfo *answer);
40
bool connect_TCP_socket(int sockfd, struct addrinfo *addr);
41
bool nts_set_cert_search(SSL_CTX *ctx, const char *filename);
42
void set_hostname(SSL *ssl, const char *hostname);
43
bool check_certificate(SSL *ssl, struct peer *peer);
44
bool check_alpn(SSL *ssl, struct peer *peer, const char *hostname);
45
bool nts_client_send_request(SSL *ssl, struct peer *peer);
46
bool nts_client_send_request_core(uint8_t *buff, int buf_size, int *used, struct peer* peer);
47
bool nts_client_process_response(SSL *ssl, struct peer *peer);
48
bool nts_client_process_response_core(uint8_t *buff, int transferred, struct peer* peer);
49
bool nts_server_lookup(char *server, sockaddr_u *addr, int af);
50
51
static SSL_CTX *client_ctx = NULL;
52
53
/* Ugly global variables passed from worker thread back to main thread. */
54
static sockaddr_u sockaddr;
55
static bool addrOK;
56
57
58
0
bool nts_client_init(void) {
59
60
0
  client_ctx = make_ssl_client_ctx(ntsconfig.ca);
61
62
63
/* Ugly global variables passed from worker thread back to main thread. */
64
0
  return true;
65
0
}
66
67
0
bool nts_probe(struct peer * peer) {
68
0
  struct timeval timeout = {.tv_sec = NTS_KE_TIMEOUT, .tv_usec = 0};
69
0
  const char *hostname = peer->hostname;
70
0
  char hostbuf[100];
71
0
  char errbuf[100];
72
0
  SSL     *ssl;
73
0
  int      server;
74
0
  struct timespec start, finish;
75
0
  int      err;
76
77
0
  if (NULL == client_ctx)
78
0
    return false;
79
80
0
  addrOK = false;
81
0
  clock_gettime(CLOCK_MONOTONIC, &start);
82
83
0
  if (NULL == hostname) {
84
    /* IP Address case */
85
0
    int af = AF(&peer->srcadr);
86
0
    switch (af) {
87
0
        case AF_INET:
88
0
      inet_ntop(af, PSOCK_ADDR4(&peer->srcadr), hostbuf, sizeof(hostbuf));
89
0
      break;
90
0
        case AF_INET6:
91
0
      inet_ntop(af, PSOCK_ADDR6(&peer->srcadr), hostbuf, sizeof(hostbuf));
92
0
      break;
93
0
        default:
94
0
      return false;
95
0
    }
96
0
    hostname = hostbuf;
97
0
  }
98
99
0
  server = open_TCP_socket(peer, hostname);
100
0
  if (-1 == server) {
101
0
    ntske_cnt.probes_bad++;
102
0
    return false;
103
0
  }
104
105
0
  err = setsockopt(server, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
106
0
  if (0 > err) {
107
0
    ntp_strerror_r(errno, errbuf, sizeof(errbuf));
108
0
    msyslog(LOG_ERR, "NTSc: can't setsockopt: %s", errbuf);
109
0
    close(server);
110
0
    ntske_cnt.probes_bad++;
111
0
    return false;
112
0
  }
113
114
0
  if (NULL == peer->cfg.nts_cfg.ca)
115
0
    ssl = SSL_new(client_ctx);
116
0
  else {
117
0
    SSL_CTX *ctx;
118
0
    ctx = make_ssl_client_ctx(peer->cfg.nts_cfg.ca);
119
0
    if (NULL == ctx) {
120
0
      close(server);
121
0
      return false;
122
0
    }
123
0
    ssl = SSL_new(ctx);
124
0
    SSL_CTX_free(ctx);
125
0
  }
126
0
  set_hostname(ssl, hostname);
127
0
  SSL_set_fd(ssl, server);
128
129
0
  if (1 != SSL_connect(ssl)) {
130
0
    msyslog(LOG_INFO, "NTSc: SSL_connect failed");
131
0
    nts_log_ssl_error();
132
0
    goto bail;
133
0
  }
134
0
  if (1 != SSL_do_handshake(ssl)) {
135
0
    msyslog(LOG_INFO, "NTSc: SSL_do_handshake failed");
136
0
    nts_log_ssl_error();
137
0
    goto bail;
138
0
  }
139
140
  /* This may be clutter, but this is how to do it. */
141
0
  msyslog(LOG_INFO, "NTSc: Using %s, %s (%d)",
142
0
    SSL_get_version(ssl),
143
0
    SSL_get_cipher_name(ssl),
144
0
    SSL_get_cipher_bits(ssl, NULL));
145
146
0
  if (!check_certificate(ssl, peer))
147
0
    goto bail;
148
0
  if (!check_alpn(ssl, peer, hostname))
149
0
    goto bail;
150
151
0
  if (!nts_client_send_request(ssl, peer))
152
0
    goto bail;
153
0
  if (!nts_client_process_response(ssl, peer))
154
0
    goto bail;
155
156
  /* We are using AEAD_AES_SIV_CMAC_xxx, from RFC 5297
157
   * key length depends upon which key is selected */
158
0
  peer->nts_state.keylen = nts_get_key_length(peer->nts_state.aead);
159
0
  if (0 == peer->nts_state.keylen) {
160
0
    msyslog(LOG_ERR, "NTSc: Unknown AEAD code: %d", peer->nts_state.aead);
161
0
    goto bail;
162
0
  }
163
0
  if (!nts_make_keys(ssl,
164
0
         peer->nts_state.aead,
165
0
         peer->nts_state.c2s,
166
0
         peer->nts_state.s2c,
167
0
         peer->nts_state.keylen))
168
0
    goto bail;
169
170
0
  addrOK = true;
171
0
  ntske_cnt.probes_good++;
172
173
0
  bail:
174
0
  if (!addrOK) {
175
0
    ntske_cnt.probes_bad++;
176
0
    peer->nts_state.count = -1;
177
0
  }
178
0
  SSL_shutdown(ssl);
179
0
  SSL_free(ssl);
180
0
  close(server);
181
182
0
  clock_gettime(CLOCK_MONOTONIC, &finish);
183
0
  finish = sub_tspec(finish, start);
184
0
  msyslog(LOG_INFO, "NTSc: NTS-KE req to %s took %.3f sec, %s",
185
0
    hostname, tspec_to_d(finish),
186
0
    addrOK? "OK" : "fail");
187
188
0
  return addrOK;
189
0
}
190
191
0
bool nts_check(struct peer *peer) {
192
0
  if (0) {
193
0
    char errbuf[100];
194
0
    sockporttoa_r(&sockaddr, errbuf, sizeof(errbuf));
195
0
    msyslog(LOG_INFO, "NTSc: nts_check %s, %d", errbuf, addrOK);
196
0
  }
197
0
  if (addrOK) {
198
0
    dns_take_server(peer, &sockaddr);
199
0
    dns_take_status(peer, DNS_good);
200
0
  } else
201
0
    dns_take_status(peer, DNS_error);
202
0
  return addrOK;
203
0
}
204
205
0
SSL_CTX* make_ssl_client_ctx(const char * filename) {
206
0
  bool ok = true;
207
0
  SSL_CTX *ctx;
208
209
0
  ctx = SSL_CTX_new(TLS_client_method());
210
0
  if (NULL == ctx) {
211
    /* Happens if no ciphers */
212
0
    msyslog(LOG_ERR, "NTSc: NULL ctx");
213
0
    nts_log_ssl_error();
214
0
    return NULL;
215
0
  }
216
217
0
  {
218
    // 4., ALPN, RFC 7301
219
0
    static unsigned char alpn [] = { 7, 'n', 't', 's', 'k', 'e', '/', '1' };
220
0
    SSL_CTX_set_alpn_protos(ctx, alpn, sizeof(alpn));
221
0
  }
222
223
0
  SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
224
0
  SSL_CTX_set_timeout(ctx, NTS_KE_TIMEOUT);   /* session lifetime */
225
226
0
  ok &= nts_load_versions(ctx);
227
0
  ok &= nts_load_ciphers(ctx);
228
0
  ok &= nts_load_ecdhcurves(ctx);
229
0
  ok &= nts_set_cert_search(ctx, filename);
230
231
0
  if (!ok) {
232
0
    msyslog(LOG_ERR, "NTSc: Troubles setting up client SSL CTX");
233
0
    SSL_CTX_free(ctx);
234
0
    return NULL;
235
0
  };
236
237
0
  return ctx;
238
0
}
239
240
/* return -1 on error */
241
0
int open_TCP_socket(struct peer *peer, const char *hostname) {
242
0
  char host[256], port[32];
243
0
  char errbuf[100];
244
0
  char *tmp;
245
0
  struct addrinfo hints;
246
0
  struct addrinfo *answer, *worker;
247
0
  int gai_rc;
248
0
  int sockfd;
249
0
  struct timespec start, finish;
250
251
  /* copy avoids dancing around const warnings */
252
0
  strlcpy(host, hostname, sizeof(host));
253
254
  /* handle xxx:port case */
255
0
  tmp = strchr(host, ']');
256
0
  if (NULL == tmp) {
257
0
    tmp = strchr(host, ':');
258
0
  } else {
259
    /* IPv6 case, start search after ] */
260
0
    tmp = strchr(tmp, ':');
261
0
  }
262
0
  if (NULL == tmp) {
263
    /* simple case, no : */
264
0
    strlcpy(port, NTS_KE_PORTA, sizeof(port));
265
0
  } else {
266
    /* Complicated case, found a : */
267
0
    *tmp++ = 0;
268
0
    strlcpy(port, tmp, sizeof(port));
269
0
  }
270
271
0
  ZERO(hints);
272
0
  hints.ai_protocol = IPPROTO_TCP;
273
0
  hints.ai_socktype = SOCK_STREAM;
274
0
  hints.ai_family = AF(&peer->srcadr);  /* -4, -6 switch */
275
0
  clock_gettime(CLOCK_MONOTONIC, &start);
276
0
  gai_rc = getaddrinfo(host, port, &hints, &answer);
277
0
  if (0 != gai_rc) {
278
0
    msyslog(LOG_INFO, "NTSc: open_TCP_socket: DNS error trying to contact %s: %d, %s",
279
0
      hostname, gai_rc, gai_strerror(gai_rc));
280
0
    return -1;
281
0
  }
282
0
  clock_gettime(CLOCK_MONOTONIC, &finish);
283
0
  finish = sub_tspec(finish, start);
284
0
  msyslog(LOG_INFO, "NTSc: DNS lookup of %s took %.3f sec",
285
0
    hostname, tspec_to_d(finish));
286
287
  /* Use first answer
288
   * sockaddr is global for NTP address
289
   * also use as temp for printing here
290
   */
291
0
  worker = find_best_addr(answer);
292
0
  memcpy(&sockaddr, worker->ai_addr, worker->ai_addrlen);
293
0
  sockporttoa_r(&sockaddr, errbuf, sizeof(errbuf));
294
0
  msyslog(LOG_INFO, "NTSc: connecting to %s:%s => %s",
295
0
    host, port, errbuf);
296
297
  /* setup default NTP port now
298
   *   in case of server-name:port later on
299
   */
300
0
  SET_PORT(&sockaddr, NTP_PORT);
301
0
  sockfd = socket(worker->ai_family, SOCK_STREAM, 0);
302
0
  if (-1 == sockfd) {
303
0
    ntp_strerror_r(errno, errbuf, sizeof(errbuf));
304
0
    msyslog(LOG_INFO, "NTSc: open_TCP_socket: no socket: %s", errbuf);
305
0
  } else {
306
    /* Use first IP Address */
307
0
    if (!connect_TCP_socket(sockfd, worker)) {
308
0
      close(sockfd);
309
0
      sockfd = -1;
310
0
    }
311
0
  }
312
313
0
  freeaddrinfo(answer);
314
0
  return sockfd;
315
316
0
}
317
318
0
struct addrinfo *find_best_addr(struct addrinfo *answer) {
319
  /* default to first one */
320
0
  return(answer);
321
0
}
322
323
324
/* This kludgery is needed to get a sane timeout.
325
 * The default is unspecified but long.
326
 * On Linux, man connect gets man 2 which doesn't mention O_NONBLOCK
327
 * Use man 3 connect.
328
 */
329
0
bool connect_TCP_socket(int sockfd, struct addrinfo *addr) {
330
0
  char errbuf[100];
331
0
  int err;
332
0
  fd_set fdset;
333
0
  struct timeval timeout;
334
0
  int so_error;
335
0
  socklen_t so_len = sizeof(so_error);
336
337
0
  err = fcntl(sockfd, F_SETFL, O_NONBLOCK);
338
0
  if (-1 == err) {
339
0
    ntp_strerror_r(errno, errbuf, sizeof(errbuf));
340
0
    msyslog(LOG_INFO, "NTSc: can't set O_NONBLOCK %s", errbuf);
341
0
    return false;
342
0
  }
343
0
  err = connect(sockfd, addr->ai_addr, addr->ai_addrlen);
344
  /* The normal case is -1 and errno == EINPROGRESS
345
   * Getting connected should be possible if the scheduler
346
   * avoids us for long enough.
347
   * Other errors may be possible.  No route?
348
   * I haven't seen that yet.  HGM, 2020 Jan 19
349
   */
350
0
  if (-1 != err || EINPROGRESS != errno) {
351
0
    ntp_strerror_r(errno, errbuf, sizeof(errbuf));
352
0
    msyslog(LOG_INFO, "NTSc: connect_TCP_socket: connect failed: %s", errbuf);
353
0
    return false;
354
0
  }
355
356
0
  FD_ZERO(&fdset);
357
0
  FD_SET(sockfd, &fdset);
358
0
  timeout.tv_sec = NTS_KE_TIMEOUT;
359
0
  timeout.tv_usec = 0;
360
361
0
  if (0 == select(sockfd + 1, NULL, &fdset, NULL, &timeout)) {
362
0
    msyslog(LOG_INFO, "NTSc: connect_TCP_socket: timeout");
363
0
    return false;
364
0
  }
365
366
  /* It's ready, either connected or error. */
367
0
  if (-1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &so_error, &so_len)) {
368
0
    ntp_strerror_r(errno, errbuf, sizeof(errbuf));
369
0
    msyslog(LOG_INFO, "NTSc: connect_TCP_socket: getsockopt failed: %s", errbuf);
370
0
    return false;
371
0
  }
372
373
0
  if (0 != so_error) {
374
0
    ntp_strerror_r(so_error, errbuf, sizeof(errbuf));
375
0
    msyslog(LOG_INFO, "NTSc: connect_TCP_socket: connect failed: %s", errbuf);
376
0
    return false;
377
0
  }
378
379
0
  err = fcntl(sockfd, F_SETFL, 0); /* turn off O_NONBLOCK */
380
0
  if (-1 == err) {
381
0
    ntp_strerror_r(errno, errbuf, sizeof(errbuf));
382
0
    msyslog(LOG_INFO, "NTSc: can't unset O_NONBLOCK %s", errbuf);
383
0
    return false;
384
0
  }
385
386
0
  return true;
387
0
}
388
389
390
0
void set_hostname(SSL *ssl, const char *hostname) {
391
0
  char host[256], *tmp;
392
393
  /* chop off trailing :port */
394
0
  strlcpy(host, hostname, sizeof(host));
395
0
  tmp = strchr(host, ']');
396
0
  if (NULL == tmp) {
397
0
    tmp = host;     /* not IPv6 [...] format */
398
0
  }
399
0
  tmp = strchr(tmp, ':');
400
0
  if (NULL != tmp) {
401
0
    *tmp = 0;
402
0
  }
403
404
/* https://wiki.openssl.org/index.php/Hostname_validation
405
 * draft-ietf-uta-rfc6125bis section 3 relaxes the restrictions around the use
406
 * of wildcards to make it clear that they're permitted unless specifically
407
 * prohibited in an RFC
408
 */
409
0
  SSL_set_hostflags(ssl, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
410
0
  SSL_set1_host(ssl, host);
411
0
  msyslog(LOG_DEBUG, "NTSc: set cert host: %s", host);
412
413
0
}
414
415
0
bool check_certificate(SSL *ssl, struct peer* peer) {
416
0
  X509 *cert = SSL_get_peer_certificate(ssl);
417
0
  X509_NAME *certname;
418
0
  GENERAL_NAMES *gens;
419
0
  char name[200];
420
0
  int certok;
421
0
  int numgens = 0;
422
423
0
  if (NULL == cert) {
424
0
    msyslog(LOG_INFO, "NTSc: No certificate");
425
0
    if (!(FLAG_NTS_NOVAL & peer->cfg.flags))
426
0
      return false;
427
0
    return true;
428
0
  }
429
430
0
  certname = X509_get_subject_name(cert);
431
0
  X509_NAME_oneline(certname, name, sizeof(name));
432
0
  msyslog(LOG_INFO, "NTSc: certificate subject name: %s", name);
433
0
  certname = X509_get_issuer_name(cert);
434
0
  X509_NAME_oneline(certname, name, sizeof(name));
435
0
  msyslog(LOG_INFO, "NTSc: certificate issuer name: %s", name);
436
  /* print SAN:DNS strings */
437
0
  gens = X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0);
438
0
  if (gens) {
439
0
    char buff[150];
440
0
    numgens = sk_GENERAL_NAME_num(gens);
441
0
    buff[0] = 0;
442
0
    for (int i = 0; i<numgens; i++) {
443
0
      const GENERAL_NAME *gen;
444
0
      const char *dnsname;
445
0
      unsigned int len;
446
0
      gen = sk_GENERAL_NAME_value(gens, i);
447
0
      if (gen->type != GEN_DNS)
448
0
        continue;
449
      // string is NUL terminated but may have internal NULs
450
0
      len = (unsigned int)ASN1_STRING_length(gen->d.ia5);
451
0
      dnsname = (const char *)ASN1_STRING_get0_data(gen->d.ia5);
452
0
      if (0 != buff[0])
453
0
        strlcat(buff, ", ", sizeof(buff));
454
0
      strlcat(buff, dnsname, sizeof(buff));
455
0
      if (len != strlen(dnsname))
456
0
        strlcat(buff, "??", sizeof(buff));
457
0
    }
458
0
    msyslog(LOG_INFO, "NTSc: SAN:DNS %s", buff);
459
0
    GENERAL_NAMES_free(gens);
460
0
  }
461
0
  if (0 == numgens) {
462
0
    const char *peername = SSL_get0_peername(ssl);
463
0
    msyslog(LOG_INFO, "NTSc: matching with subject:CN %s", peername);
464
0
  } else if (1 > numgens) {
465
0
    const char *peername = SSL_get0_peername(ssl);
466
0
    msyslog(LOG_INFO, "NTSc: matching with SAN:DNS: %s", peername);
467
0
  }
468
0
  X509_free(cert);
469
0
  certok = SSL_get_verify_result(ssl);
470
0
  if (X509_V_OK == certok) {
471
0
    msyslog(LOG_INFO, "NTSc: certificate is valid.");
472
0
  } else {
473
0
    msyslog(LOG_ERR, "NTSc: certificate invalid: %d=>%s",
474
0
      certok, X509_verify_cert_error_string(certok));
475
0
    if (FLAG_NTS_NOVAL & peer->cfg.flags) {
476
0
      msyslog(LOG_INFO, "NTSc: noval - accepting invalid cert.");
477
0
      return true;
478
0
    }
479
0
    return false;
480
0
  }
481
0
  return true;
482
0
}
483
484
0
bool check_alpn(SSL *ssl, struct peer* peer, const char *hostname) {
485
0
  UNUSED_ARG(peer);
486
0
  const unsigned char *data;
487
0
  unsigned int len;
488
0
  SSL_get0_alpn_selected(ssl, &data, &len);
489
0
  if (0 == len) {
490
0
    msyslog(LOG_DEBUG, "NTSc: No ALPN from %s (%s)",
491
0
      hostname, SSL_get_version(ssl));
492
0
    return false;
493
0
  }
494
  /* For now, we only support one version.
495
   * This will get more complicated when version 2 arrives. */
496
0
  if (len != 7 ||
497
0
      0 != memcmp(data, "ntske/1", len)) {
498
    /* copy data over so we can print it. */
499
    /* don't read past end of data */
500
0
    unsigned int i, l;
501
0
    char buff [16];
502
0
    l = min(len, sizeof(buff)-1);
503
0
    memcpy(buff, data, l);
504
0
    buff[l] = '\0';
505
0
    for (i=0; i<l; i++) {
506
0
      if (!isgraph((int)buff[i])) {
507
0
        buff[i] = '*'; /* fix non-printing crap */
508
0
      }
509
0
    }
510
0
    msyslog(LOG_DEBUG, "NTSc: Strange ALPN %s (%u) from %s",
511
0
      buff, len, hostname);
512
0
    return false;
513
0
  }
514
0
  msyslog(LOG_DEBUG, "NTSc: Good ALPN from %s", hostname);
515
516
0
  return true;
517
0
}
518
519
0
bool nts_make_keys(SSL *ssl, uint16_t aead, uint8_t *c2s, uint8_t *s2c, int keylen) {
520
0
  const char *label = "EXPORTER-network-time-security";
521
0
  unsigned char context[5];
522
0
  context[0] = (nts_protocol_NTP >> 8) & 0xFF;
523
0
  context[1] = nts_protocol_NTP & 0xFF;
524
0
  context[2] = (aead >> 8) & 0xFF;
525
0
  context[3] = aead & 0xFF;
526
0
  context[4] = 0x00;
527
0
  if (1 != SSL_export_keying_material(ssl, c2s, keylen,
528
0
              label, strlen(label),
529
0
              context, 5, 1)) {
530
0
    msyslog(LOG_ERR, "NTS: Error making c2s\n");
531
0
    nts_log_ssl_error();
532
0
    return false;
533
0
  }
534
0
  context[4] = 0x01;
535
0
  if (1 != SSL_export_keying_material(ssl, s2c, keylen,
536
0
              label, strlen(label),
537
0
              context, 5, 1)) {
538
0
    msyslog(LOG_ERR, "NTS: Error making s2c\n");
539
0
    nts_log_ssl_error();
540
0
    return false;
541
0
  }
542
0
  return true;
543
0
}
544
545
0
bool nts_client_send_request(SSL *ssl, struct peer* peer) {
546
0
  uint8_t buff[1000];
547
0
  int     used, transferred;
548
0
  bool    success;
549
550
0
  success = nts_client_send_request_core(buff, sizeof(buff), &used, peer);
551
0
  if (!success) {
552
0
    return false;
553
0
  }
554
555
0
  transferred = nts_ssl_write(ssl, buff, used);
556
0
  if (used != transferred)
557
0
    return false;
558
559
0
  return true;
560
0
}
561
562
0
bool nts_client_send_request_core(uint8_t *buff, int buf_size, int *used, struct peer* peer) {
563
0
  struct  BufCtl_t buf;
564
0
  uint16_t aead = NO_AEAD;
565
566
0
  buf.next = buff;
567
0
  buf.left = buf_size;
568
569
  /* 4.1.2 Next Protocol, 0 for NTP */
570
0
  ke_append_record_uint16(&buf,
571
0
        NTS_CRITICAL+nts_next_protocol_negotiation, nts_protocol_NTP);
572
573
  /* 4.1.5 AEAD Algorithm List */
574
  // FIXME should be : separated list
575
576
0
  if ((NO_AEAD == aead) && (NULL != peer->cfg.nts_cfg.aead))
577
0
    aead = nts_string_to_aead(peer->cfg.nts_cfg.aead);
578
0
  if ((NO_AEAD == aead) && (NULL != ntsconfig.aead))
579
0
    aead = nts_string_to_aead(ntsconfig.aead);
580
0
  if (NO_AEAD == aead)
581
0
    aead = AEAD_AES_SIV_CMAC_256;
582
0
  ke_append_record_uint16(&buf, nts_algorithm_negotiation, aead);
583
584
  /* 4.1.1: End, Critical */
585
0
  ke_append_record_null(&buf, NTS_CRITICAL+nts_end_of_message);
586
587
0
  *used = buf_size-buf.left;
588
0
  if (*used >= (int)(buf_size - 10)) {
589
0
    msyslog(LOG_ERR, "ERR-NTSc: buffer overflow: %d, %ld",
590
0
      *used, (long)buf_size);
591
0
    exit(2);
592
0
  }
593
0
  return true;
594
0
}
595
596
0
bool nts_client_process_response(SSL *ssl, struct peer* peer) {
597
0
  uint8_t  buff[2048];  /* RFC 4. says SHOULD be 65K */
598
0
  int transferred;
599
600
0
  transferred = nts_ssl_read(ssl, buff, sizeof(buff));
601
0
  if (0 > transferred)
602
0
    return false;
603
0
  msyslog(LOG_ERR, "NTSc: read %d bytes", transferred);
604
605
0
  return nts_client_process_response_core(buff, transferred, peer);
606
0
}
607
608
306
bool nts_client_process_response_core(uint8_t *buff, int transferred, struct peer* peer) {
609
306
  int idx;
610
306
  struct BufCtl_t buf;
611
612
306
  peer->nts_state.aead = NO_AEAD;
613
306
  peer->nts_state.keylen = 0;
614
306
  peer->nts_state.writeIdx = 0;
615
306
  peer->nts_state.readIdx = 0;
616
306
  peer->nts_state.count = 0;
617
618
306
  buf.next = buff;
619
306
  buf.left = transferred;
620
3.12k
  while (buf.left >= NTS_KE_HDR_LNG) {
621
3.01k
    uint16_t type, data, port;
622
3.01k
    bool critical = false;
623
3.01k
    int length, keylength;
624
3.01k
    char errbuf[100];
625
3.01k
#define MAX_SERVER 100
626
3.01k
    char server[MAX_SERVER];
627
628
3.01k
    type = ke_next_record(&buf, &length);
629
3.01k
    if (NTS_CRITICAL & type) {
630
1.51k
      critical = true;
631
1.51k
      type &= ~NTS_CRITICAL;
632
1.51k
    }
633
3.01k
    if (0) // Handy for debugging but very verbose
634
0
      msyslog(LOG_ERR, "NTSc: Record: T=%d, L=%d, C=%d", type, length, critical);
635
3.01k
    switch (type) {
636
17
        case nts_error:
637
17
      data = next_uint16(&buf);
638
17
      if (sizeof(data) != length)
639
16
        msyslog(LOG_ERR, "NTSc: wrong length on error: %d", length);
640
17
      msyslog(LOG_ERR, "NTSc: error: %d", data);
641
17
      return false;
642
239
        case nts_next_protocol_negotiation:
643
239
      data = next_uint16(&buf);
644
239
      if ((sizeof(data) != length) || (data != nts_protocol_NTP)) {
645
36
        msyslog(LOG_ERR, "NTSc: NPN-Wrong length or bad data: %d, %d",
646
36
          length, data);
647
36
        return false;
648
36
      }
649
203
      break;
650
273
        case nts_algorithm_negotiation:
651
273
      data = next_uint16(&buf);
652
273
      if (sizeof(data) != length) {
653
20
        msyslog(LOG_ERR, "NTSc: AN-Wrong length: %d", length);
654
20
        return false;
655
20
      }
656
253
      keylength = nts_get_key_length(data);
657
253
      if (0 == keylength) {
658
17
        msyslog(LOG_ERR, "NTSc: AN-Unsupported AEAN type: %d", data);
659
17
        return false;
660
17
      }
661
236
      peer->nts_state.aead = data;
662
236
      break;
663
1.01k
        case nts_new_cookie:
664
1.01k
      if (NTS_MAX_COOKIELEN < length) {
665
4
        msyslog(LOG_ERR, "NTSc: NC cookie too big: %d", length);
666
4
        return false;
667
4
      }
668
1.00k
      if (0 == peer->nts_state.cookielen)
669
765
        peer->nts_state.cookielen = length;
670
1.00k
      if (length != peer->nts_state.cookielen) {
671
24
        msyslog(LOG_ERR, "NTSc: Cookie length mismatch %d, %d.",
672
24
          length, peer->nts_state.cookielen);
673
24
        return false;
674
24
      }
675
983
      idx = peer->nts_state.writeIdx;
676
983
      if (NTS_MAX_COOKIES <= peer->nts_state.count) {
677
534
        msyslog(LOG_ERR, "NTSc: Extra cookie ignored.");
678
534
        break;
679
534
      }
680
449
      next_bytes(&buf, (uint8_t*)&peer->nts_state.cookies[idx], length);
681
449
      peer->nts_state.writeIdx++;
682
449
      peer->nts_state.writeIdx = peer->nts_state.writeIdx % NTS_MAX_COOKIES;
683
449
      peer->nts_state.count++;
684
449
      break;
685
555
        case nts_server_negotiation:
686
555
      if (MAX_SERVER < (length+1)) {
687
12
        msyslog(LOG_ERR, "NTSc: server string too long %d.", length);
688
12
        return false;
689
12
      }
690
543
      next_bytes(&buf, (uint8_t *)server, length);
691
543
      server[length] = '\0';
692
      /* save port in case port specified before server */
693
543
      port = SRCPORT(&sockaddr);
694
543
      if (!nts_server_lookup(server, &sockaddr, AF(&peer->srcadr)))
695
13
        return false;
696
530
      SET_PORT(&sockaddr, port);
697
530
      socktoa_r(&sockaddr, errbuf, sizeof(errbuf));
698
530
      msyslog(LOG_ERR, "NTSc: Using server %s=>%s", server, errbuf);
699
530
      break;
700
234
        case nts_port_negotiation:
701
234
      if (sizeof(port) != length) {
702
17
        msyslog(LOG_ERR, "NTSc: PN-Wrong length: %d, %d",
703
17
          length, critical);
704
17
        return false;
705
17
      }
706
217
      port = next_uint16(&buf);
707
217
      SET_PORT(&sockaddr, port);
708
217
      msyslog(LOG_ERR, "NTSc: Using port %d", port);
709
217
      break;
710
28
        case nts_end_of_message:
711
28
      if ((0 != length) || !critical) {
712
12
        msyslog(LOG_ERR, "NTSc: EOM-Wrong length or not Critical: %d, %d",
713
12
          length, critical);
714
12
        return false;
715
12
      }
716
16
      if (0 != buf.left) {
717
13
        msyslog(LOG_ERR, "NTSc: EOM not at end: %d", buf.left);
718
13
        return false;
719
13
      }
720
3
      break;
721
659
        default:
722
659
      msyslog(LOG_ERR, "NTSc: received strange type: T=%d, C=%d, L=%d",
723
659
        type, critical, length);
724
659
      if (critical) {
725
11
        return false;
726
11
      }
727
648
      buf.next += length;
728
648
      buf.left -= length;
729
648
      break;
730
3.01k
    } /* case */
731
3.01k
  }   /* while */
732
733
110
  if (buf.left > 0)
734
12
    return false;
735
736
98
  if (NO_AEAD == peer->nts_state.aead) {
737
82
    msyslog(LOG_ERR, "NTSc: No AEAD algorithim.");
738
82
    return false;
739
82
  }
740
16
  if (0 == peer->nts_state.count) {
741
12
    msyslog(LOG_ERR, "NTSc: No cookies.");
742
12
    return false;
743
12
  }
744
745
4
  msyslog(LOG_ERR, "NTSc: Got %d cookies, length %d, aead=%d.",
746
4
    peer->nts_state.count, peer->nts_state.cookielen, peer->nts_state.aead);
747
4
  return true;
748
16
}
749
750
0
bool nts_set_cert_search(SSL_CTX *ctx, const char *filename) {
751
0
  struct stat statbuf;
752
0
  char errbuf[100];
753
0
  if (NULL == filename) {
754
0
    msyslog(LOG_INFO, "NTSc: Using system default root certificates.");
755
0
    SSL_CTX_set_default_verify_paths(ctx);   // Use system root certs
756
0
    return true;
757
0
  }
758
0
  if (0 == stat(filename, &statbuf)) {
759
0
    if (S_ISDIR(statbuf.st_mode)) {
760
0
      if (1 != SSL_CTX_load_verify_locations(
761
0
        ctx, NULL, filename)) {
762
0
      msyslog(LOG_INFO, "NTSc: Can't use %s as dir for root certificates.", filename);
763
0
          nts_log_ssl_error();
764
0
          return false;
765
0
      }
766
0
      msyslog(LOG_INFO, "NTSc: Using dir %s for root certificates.", filename);
767
0
      return true;
768
0
    }
769
0
    if (S_ISREG(statbuf.st_mode)) {
770
0
      if (1 != SSL_CTX_load_verify_locations(
771
0
        ctx, filename, NULL)) {
772
0
          msyslog(LOG_INFO, "NTSc: Can't use %s as file for root certificates.", filename);
773
0
          nts_log_ssl_error();
774
0
          return false;
775
0
      }
776
0
      msyslog(LOG_INFO, "NTSc: Using file %s for root certificates.", filename);
777
0
      return true;
778
0
    }
779
0
    msyslog(LOG_ERR, "NTSc: cert dir/file isn't dir or file: %s. mode 0x%x",
780
0
      filename, statbuf.st_mode);
781
0
    return false;
782
0
  }
783
0
  ntp_strerror_r(errno, errbuf, sizeof(errbuf));
784
0
  msyslog(LOG_ERR, "NTSc: can't stat cert dir/file: %s, %s",
785
0
    filename, errbuf);
786
0
  return false;
787
0
}
788
/* The -4/-6 option is used for both the NTS-KE server and the NTP server.
789
 * That will break if the KE server returns a name that returns only an
790
 * address of the other type.
791
 * We could fix that by trying again with AF_UNSPEC.
792
 */
793
543
bool nts_server_lookup(char *server, sockaddr_u *addr, int af) {
794
543
  struct addrinfo hints;
795
543
  struct addrinfo *answer = NULL;  /* init to keep oss-fuzz happy */
796
543
  int gai_rc;
797
798
543
  ZERO(hints);
799
543
  hints.ai_protocol = IPPROTO_UDP;
800
543
  hints.ai_socktype = SOCK_DGRAM;
801
543
  hints.ai_family = af;
802
803
543
  gai_rc = getaddrinfo(server, NTS_KE_PORTA, &hints, &answer);
804
543
  if (0 != gai_rc) {
805
13
    msyslog(LOG_INFO, "NTSc: DNS error trying to lookup %s: %d, %s",
806
13
      server, gai_rc, gai_strerror(gai_rc));
807
13
    return false;
808
13
  }
809
810
530
  if (NULL == answer)
811
0
    return false;
812
813
530
  if (sizeof(sockaddr_u) >= answer->ai_addrlen)
814
530
    memcpy(addr, answer->ai_addr, answer->ai_addrlen);
815
816
530
  freeaddrinfo(answer);
817
818
530
  return true;
819
530
}
820
821
/* end */