Coverage Report

Created: 2026-01-09 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ntpsec/ntpd/nts_server.c
Line
Count
Source
1
/*
2
 * nts_server.c - Network Time Security (NTS) server 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 <signal.h>
13
#include <pthread.h>
14
#include <unistd.h>
15
#include <sys/socket.h>
16
#include <sys/time.h>
17
#include <sys/resource.h>
18
19
#include <openssl/ssl.h>
20
#include <openssl/err.h>
21
#include <openssl/x509.h>
22
23
#include "ntp.h"
24
#include "ntpd.h"
25
#include "ntp_stdlib.h"
26
#include "nts.h"
27
#include "nts2.h"
28
#include "timespecops.h"
29
30
/* Beware: bind and accept take type sockaddr, but that's not big
31
 *         enough for an IPv6 address.
32
 */
33
34
35
static bool create_listener4(int port);
36
static bool create_listener6(int port);
37
static void* nts_ke_listener(void*);
38
static void nts_ke_request(SSL *ssl, const char **errtxt);
39
static void nts_ke_accept_fail(char* hostname, double sec, int code);
40
41
static void nts_lock_certlock(void);
42
static void nts_unlock_certlock(void);
43
44
45
static SSL_CTX *server_ctx = NULL;
46
static int listener4_sock = -1;
47
static int listener6_sock = -1;
48
49
static void nts_ke_setup_send(struct BufCtl_t *buf, int aead,
50
       uint8_t *c2s, uint8_t *s2c, int keylen);
51
52
/* We need a lock to protect reloading our certificate.
53
 * This seems like overkill, but it doesn't happen often. */
54
pthread_mutex_t certificate_lock = PTHREAD_MUTEX_INITIALIZER;
55
56
static int alpn_select_cb(SSL *ssl,
57
        const unsigned char **out,
58
        unsigned char *outlen,
59
        const unsigned char *in,
60
        unsigned int inlen,
61
        void *arg)
62
0
{
63
0
  static const unsigned char alpn[] = {
64
0
            'n', 't', 's', 'k', 'e', '/', '1' };
65
0
  unsigned i, len;
66
67
0
  UNUSED_ARG(ssl);
68
0
  UNUSED_ARG(arg);
69
70
0
  for (i = 0; i < inlen; i += len+1) {
71
0
    len = in[i]; // first byte is the length
72
#if 0
73
    char foo[256];
74
    strlcpy(foo, (const char*)in+i+1, len);
75
    msyslog(LOG_DEBUG, "DEBUG: alpn_select_cb:  %u, %u, %s", inlen-i, len, foo);
76
#endif
77
0
    if (len+1 > inlen-i)
78
      /* bogus arg: length overlaps end of in buffer */
79
0
      return SSL_TLSEXT_ERR_ALERT_FATAL;
80
0
    if (len == sizeof(alpn) && !memcmp(in+i+1, alpn, len)) {
81
0
      *out = in+i+1;
82
0
      *outlen = len;
83
0
      return SSL_TLSEXT_ERR_OK;
84
0
    }
85
0
  }
86
87
0
  return SSL_TLSEXT_ERR_NOACK;
88
0
}
89
90
0
bool nts_server_init(void) {
91
0
  bool ok = true;
92
93
0
  msyslog(LOG_INFO, "NTSs: starting NTS-KE server listening on port %d",
94
0
    NTS_KE_PORT);
95
96
0
  server_ctx = SSL_CTX_new(TLS_server_method());
97
0
  if (NULL == server_ctx) {
98
    /* Happens if no ciphers */
99
0
    msyslog(LOG_INFO, "NTSs: NULL server_ctx");
100
0
    nts_log_ssl_error();
101
0
    return false;
102
0
  }
103
104
0
  SSL_CTX_set_alpn_select_cb(server_ctx, alpn_select_cb, NULL);
105
0
  SSL_CTX_set_session_cache_mode(server_ctx, SSL_SESS_CACHE_OFF);
106
0
  SSL_CTX_set_timeout(server_ctx, NTS_KE_TIMEOUT);  /* session lifetime */
107
108
0
  ok &= nts_load_versions(server_ctx);
109
0
  ok &= nts_load_ciphers(server_ctx);
110
0
  ok &= nts_load_ecdhcurves(server_ctx);
111
0
  ok &= nts_set_cipher_order(server_ctx);
112
113
0
  if (!ok) {
114
0
    msyslog(LOG_ERR, "NTSs: Disabling NTS-KE server");
115
0
    SSL_CTX_free(server_ctx);
116
0
    server_ctx = NULL;
117
0
    return false;
118
0
  };
119
120
0
  msyslog(LOG_INFO, "NTSs: OpenSSL security level is %d",
121
0
    SSL_CTX_get_security_level(server_ctx));
122
123
0
  msyslog(LOG_INFO, "NTSs: starting NTS-KE server listening on port %d",
124
0
    NTS_KE_PORT);
125
0
  ok &= create_listener4(NTS_KE_PORT);
126
0
  ok &= create_listener6(NTS_KE_PORT);
127
128
0
  return ok;
129
0
}
130
131
0
bool nts_server_init2(void) {
132
0
  pthread_t worker;
133
0
  sigset_t block_mask, saved_sig_mask;
134
0
  int rc;
135
0
  char errbuf[100];
136
137
0
  if (!nts_load_certificate(server_ctx)) {
138
0
    return false;
139
0
  }
140
141
0
  sigfillset(&block_mask);
142
0
  pthread_sigmask(SIG_BLOCK, &block_mask, &saved_sig_mask);
143
0
  if (listener4_sock != -1) {
144
0
    rc = pthread_create(&worker, NULL, nts_ke_listener, &listener4_sock);
145
0
    if (rc) {
146
0
      ntp_strerror_r(errno, errbuf, sizeof(errbuf));
147
0
      msyslog(LOG_ERR, "NTSs: nts_start_server4: error from pthread_create: %s", errbuf);
148
0
    }
149
0
  }
150
0
  if (listener6_sock != -1) {
151
0
    rc = pthread_create(&worker, NULL, nts_ke_listener, &listener6_sock);
152
0
    if (rc) {
153
0
      ntp_strerror_r(errno, errbuf, sizeof(errbuf));
154
0
      msyslog(LOG_ERR, "NTSs: nts_start_server6: error from pthread_create: %s", errbuf);
155
0
    }
156
0
  }
157
0
  pthread_sigmask(SIG_SETMASK, &saved_sig_mask, NULL);
158
159
0
  return true;
160
0
}
161
162
/* called every hour */
163
0
void nts_cert_timer(void) {
164
0
  check_cert_file();
165
0
}
166
167
/* call hourly and by SIGHUP */
168
0
void check_cert_file(void) {
169
0
  if (NULL == server_ctx)
170
0
    return;
171
0
  nts_lock_certlock();
172
0
  nts_reload_certificate(server_ctx);
173
0
  nts_unlock_certlock();
174
0
}
175
176
0
void nts_lock_certlock(void) {
177
0
  int err = pthread_mutex_lock(&certificate_lock);
178
0
  if (0 != err) {
179
0
    msyslog(LOG_ERR, "ERR: Can't lock certificate_lock: %d", err);
180
0
    exit(2);
181
0
  }
182
0
}
183
184
0
void nts_unlock_certlock(void) {
185
0
  int err = pthread_mutex_unlock(&certificate_lock);
186
0
  if (0 != err) {
187
0
    msyslog(LOG_ERR, "ERR: Can't unlock certificate_lock: %d", err);
188
0
    exit(2);
189
0
  }
190
0
}
191
192
/* lfptod goes to long double */
193
0
static inline double lfptox(l_fp r) {
194
/* l_fp to double */
195
0
        return ldexp((double)((int64_t)r), -32);
196
0
}
197
198
199
0
void* nts_ke_listener(void* arg) {
200
0
  struct timeval timeout = {.tv_sec = NTS_KE_TIMEOUT, .tv_usec = 0};
201
0
  int sock = *(int*)arg;
202
0
  char errbuf[100];
203
0
  char addrbuf[100];
204
0
  char usingbuf[100];
205
0
  struct timespec start, finish;    /* wall clock */
206
0
  l_fp wall;
207
0
  const char *errtxt; /* not NULL if error */
208
0
#ifdef RUSAGE_THREAD
209
0
  struct timespec start_u, finish_u;  /* CPU user */
210
0
  struct timespec start_s, finish_s;  /* CPU system */
211
0
  l_fp usr, sys;
212
0
  struct rusage usage;
213
0
#endif
214
215
#ifdef HAVE_SECCOMP_H
216
        setup_SIGSYS_trap();   /* enable trap for this thread */
217
#endif
218
219
0
#ifdef RUSAGE_THREAD
220
  /* NB: start_u and start_s are from near the end of the previous cycle.
221
   * Thus usage timing includes the TCP accept and
222
   * writing the previous msyslog message.
223
   */
224
0
  getrusage(RUSAGE_THREAD, &usage);
225
0
  start_u = tval_to_tspec(usage.ru_utime);
226
0
  start_s = tval_to_tspec(usage.ru_stime);
227
0
#endif
228
229
0
  while(1) {
230
0
    sockaddr_u addr;
231
0
    socklen_t len = sizeof(addr);
232
0
    SSL *ssl;
233
0
    int client, err;
234
235
0
    sleep(1);     /* FIXME: log clutter/DoS */
236
0
    errtxt = NULL;
237
0
    client = accept(sock, &addr.sa, &len);
238
0
    if (client < 0) {
239
0
      ntp_strerror_r(errno, errbuf, sizeof(errbuf));
240
0
      msyslog(LOG_ERR, "NTSs: TCP accept failed: %s", errbuf);
241
0
      if (EBADF == errno)
242
0
        return NULL;
243
0
      continue;
244
0
    }
245
0
    clock_gettime(CLOCK_MONOTONIC, &start);
246
0
    sockporttoa_r(&addr, addrbuf, sizeof(addrbuf));
247
248
/* This is disabled in order to reduce clutter in the log file.
249
 * The client's address is now included in the final message.
250
 * That works fine in the normal successful case.  There is one line
251
 * per connection.
252
 * The failed cases are more complicated.
253
 * The common fail case is bad guys probing which fails in SSL_accept.
254
 * That branch has its own error handling.  Again, the common cases
255
 * have one line per connection and include the client address.
256
 * Uncommon cases will include two (or more) lines.
257
 * There are many possible error messages after SSL_accept works.
258
 * In practice, they don't happen, at least not often enough to notice.
259
 * They currently get logged without the client's address.  Then they
260
 * fall into the normal (non-error) path which does include the address.
261
 * Enabling this might make strange cases easier to understand.
262
 */
263
/*    msyslog(LOG_INFO, "NTSs: TCP accept-ed from %s", addrbuf); */
264
265
0
    err = setsockopt(client, SOL_SOCKET, SO_RCVTIMEO,
266
0
      &timeout, sizeof(timeout));
267
0
    if (0 > err) {
268
0
      ntp_strerror_r(errno, errbuf, sizeof(errbuf));
269
0
      msyslog(LOG_ERR, "NTSs: can't set recv timeout: %s", errbuf);
270
0
      close(client);
271
0
      ntske_cnt.serves_bad++;
272
0
      continue;
273
0
    }
274
0
    err = setsockopt(client, SOL_SOCKET, SO_SNDTIMEO,
275
0
      &timeout, sizeof(timeout));
276
0
    if (0 > err) {
277
0
      ntp_strerror_r(errno, errbuf, sizeof(errbuf));
278
0
      msyslog(LOG_ERR, "NTSs: can't set send timeout: %s", errbuf);
279
0
      close(client);
280
0
      ntske_cnt.serves_bad++;
281
0
      continue;
282
0
    }
283
284
    /* WARN: For high volume servers, this should go in a new thread. */
285
0
    nts_lock_certlock();
286
0
    ssl = SSL_new(server_ctx);
287
0
    nts_unlock_certlock();
288
0
    SSL_set_fd(ssl, client);
289
290
0
    err = SSL_accept(ssl);
291
0
    if (0 >= err) {
292
0
      int code = SSL_get_error(ssl, err);
293
0
      clock_gettime(CLOCK_MONOTONIC, &finish);
294
0
      wall = tspec_intv_to_lfp(sub_tspec(finish, start));
295
0
      nts_ke_accept_fail(addrbuf, lfptox(wall), code);
296
0
      SSL_free(ssl);
297
0
      close(client);
298
0
      ntske_cnt.serves_nossl++;
299
0
      ntske_cnt.serves_nossl_wall += wall;
300
0
#ifdef RUSAGE_THREAD
301
0
      getrusage(RUSAGE_THREAD, &usage);
302
0
      finish_u = tval_to_tspec(usage.ru_utime);
303
0
      finish_s = tval_to_tspec(usage.ru_stime);
304
0
      usr = tspec_intv_to_lfp(sub_tspec(finish_u, start_u));
305
0
      sys = tspec_intv_to_lfp(sub_tspec(finish_s, start_s));
306
0
      start_u = finish_u;
307
0
      start_s = finish_s;
308
0
      ntske_cnt.serves_nossl_cpu += usr;
309
0
      ntske_cnt.serves_nossl_cpu += sys;
310
0
#endif
311
0
      continue;
312
0
    }
313
314
    /* Save info for final message. */
315
0
    snprintf(usingbuf, sizeof(usingbuf), "%s, %s (%d)",
316
0
      SSL_get_version(ssl),
317
0
      SSL_get_cipher_name(ssl),
318
0
      SSL_get_cipher_bits(ssl, NULL));
319
320
0
    nts_ke_request(ssl, &errtxt);
321
322
0
    SSL_shutdown(ssl);
323
0
    SSL_free(ssl);
324
0
    close(client);
325
326
0
    clock_gettime(CLOCK_MONOTONIC, &finish);
327
0
    wall = tspec_intv_to_lfp(sub_tspec(finish, start));
328
0
    if (NULL == errtxt) {
329
0
      ntske_cnt.serves_good++;
330
0
      ntske_cnt.serves_good_wall += wall;
331
0
    } else {
332
0
      ntske_cnt.serves_bad++;
333
0
      ntske_cnt.serves_bad_wall += wall;
334
0
    }
335
0
#ifdef RUSAGE_THREAD
336
0
    getrusage(RUSAGE_THREAD, &usage);
337
0
    finish_u = tval_to_tspec(usage.ru_utime);
338
0
    finish_s = tval_to_tspec(usage.ru_stime);
339
0
    usr = tspec_intv_to_lfp(sub_tspec(finish_u, start_u));
340
0
    sys = tspec_intv_to_lfp(sub_tspec(finish_s, start_s));
341
0
    start_u = finish_u;
342
0
    start_s = finish_s;
343
0
    if (NULL == errtxt) {
344
0
      ntske_cnt.serves_good_cpu += usr;
345
0
      ntske_cnt.serves_good_cpu += sys;
346
0
      msyslog(LOG_INFO,
347
0
        "NTSs: NTS-KE from %s, OK, Using %s, took %.3f sec, CPU: %.3f+%.3f ms",
348
0
        addrbuf, usingbuf, lfptox(wall),
349
0
        lfptox(usr*1000), lfptox(sys*1000));
350
0
    } else {
351
0
      ntske_cnt.serves_bad_cpu += usr;
352
0
      ntske_cnt.serves_bad_cpu += sys;
353
0
      msyslog(LOG_INFO,
354
0
        "NTSs: NTS-KE from %s, Failed, Using %s, took %.3f sec, CPU: %.3f+%.3f ms, %s",
355
0
        addrbuf, usingbuf, lfptox(wall),
356
0
        lfptox(usr*1000), lfptox(sys*1000),
357
0
        errtxt);
358
0
    }
359
#else
360
    if (NULL == errtxt) {
361
      msyslog(LOG_INFO,
362
        "NTSs: NTS-KE from %s, OK, Using %s, took %.3f sec",
363
        addrbuf, usingbuf, lfptox(wall));
364
    } else {
365
      msyslog(LOG_INFO,
366
        "NTSs: NTS-KE from %s, Failed, Using %s, took %.3f sec, %s",
367
        addrbuf, usingbuf, lfptox(wall), errtxt);
368
    }
369
#endif
370
0
  }
371
0
  return NULL;
372
0
}
373
374
/* Analyze failure from SSL_accept
375
 * print single error message for common cases.
376
 * Similar code in nts.c, nts_ssl_read() and nts_ssl_write()
377
 */
378
0
void nts_ke_accept_fail(char* hostname, double sec, int code) {
379
0
  unsigned long err = ERR_peek_error();
380
0
  char errbuf[100];
381
0
  char buff[200];
382
0
  const char *msg = NULL;
383
0
  if (0 == err) {
384
0
    switch (code) {
385
0
      case SSL_ERROR_WANT_READ:
386
0
        msg = "Timeout";
387
0
        break;
388
0
      case SSL_ERROR_SYSCALL:
389
0
        if (ECONNRESET==errno) {
390
0
          msg = "Connection reset1";
391
0
          break;
392
0
        }
393
        /* fall through */
394
0
      default:
395
0
        ntp_strerror_r(errno, errbuf, sizeof(errbuf));
396
0
        snprintf(buff, sizeof(buff), "code %d, errno=>%d, %s",
397
0
    code, errno, errbuf);
398
0
        msg = buff;
399
0
        break;
400
0
    }
401
0
  } else {
402
0
    switch (code) {
403
0
      case SSL_ERROR_SSL:
404
0
        switch (ERR_GET_REASON(err)) {
405
0
    case SSL_R_HTTP_REQUEST:
406
0
      msg = "HTTP request";
407
0
      break;
408
0
    case SSL_R_NO_SHARED_CIPHER:
409
0
                  msg = "no shared cipher";
410
0
                  break;
411
0
    case SSL_R_WRONG_VERSION_NUMBER:
412
0
                  msg = "wrong version number";
413
0
                  break;
414
0
    case SSL_R_UNSUPPORTED_PROTOCOL:
415
0
                  msg = "unsupported protocol";
416
0
                  break;
417
0
#ifdef SSL_R_UNEXPECTED_EOF_WHILE_READING
418
/* Not available in OpenSSL 1.1.1w as used by Debian 11 (bullseye), Jul 2025 */
419
0
          case SSL_R_UNEXPECTED_EOF_WHILE_READING:
420
0
      msg = "Connection reset2";
421
0
                  break;
422
0
#endif
423
0
    default:
424
      // cc (Debian 8.3.0-6) 8.3.0
425
      //   error: label at end of compound statement
426
0
      NULL;
427
          /* fall through */
428
0
        }
429
0
        if (NULL != msg) {
430
0
    err = 0;
431
0
          break;
432
0
        }
433
        /* fall through */
434
0
      default:
435
0
        ntp_strerror_r(errno, errbuf, sizeof(errbuf));
436
0
        snprintf(buff, sizeof(buff), "code %d, errno=>%d, %s, %lx=>%s",
437
0
    code, errno, errbuf, err, ERR_reason_error_string(err));
438
0
        msg = buff;
439
0
    }
440
0
  }
441
0
  msyslog(LOG_INFO, "NTSs: SSL_accept from %s, Failed, took %.3f sec, %s",
442
0
    hostname, sec, msg);
443
0
  if (err)
444
0
      nts_log_ssl_error();
445
0
}
446
447
0
void nts_ke_request(SSL *ssl, const char **errtxt) {
448
  /* RFC 4: servers must accept 1024
449
   * Our cookies can be 104, 136, or 168 for AES_SIV_CMAC_xxx
450
   * 8*168 fits comfortably into 2K.
451
   */
452
0
  uint8_t buff[2048];
453
0
  uint8_t c2s[NTS_MAX_KEYLEN], s2c[NTS_MAX_KEYLEN];
454
0
  int aead = NO_AEAD, keylen;
455
0
  struct BufCtl_t buf;
456
0
  int bytes_read, bytes_written;
457
0
  int used;
458
459
0
  bytes_read = nts_ssl_read(ssl, buff, sizeof(buff), errtxt);
460
0
  if (0 >= bytes_read)
461
0
    return;
462
463
0
  buf.next = buff;
464
0
  buf.left = bytes_read;
465
0
  if (!nts_ke_process_receive(&buf, &aead)) {
466
0
    *errtxt = "xx";
467
0
    return;
468
0
  }
469
470
0
  if ((NO_AEAD == aead) && (NULL != ntsconfig.aead))
471
0
    aead = nts_string_to_aead(ntsconfig.aead);
472
0
  if (NO_AEAD == aead)
473
0
    aead = AEAD_AES_SIV_CMAC_256;    /* default */
474
475
0
  keylen = nts_get_key_length(aead);
476
0
  if (!nts_make_keys(ssl, aead, c2s, s2c, keylen)) {
477
0
    *errtxt = "Can't make keys";
478
0
    return;
479
0
  }
480
481
0
  buf.next = buff;
482
0
  buf.left = sizeof(buff);
483
0
  nts_ke_setup_send(&buf, aead, c2s, s2c, keylen);
484
485
0
  used = sizeof(buff)-buf.left;
486
0
  bytes_written = nts_ssl_write(ssl, buff, used, errtxt);
487
0
  if (bytes_written != used)
488
0
    return;
489
490
/* FIXME: Need counters for AEAD */
491
492
0
  return;
493
0
}
494
495
0
bool create_listener4(int port) {
496
0
  int sock = -1;
497
0
  sockaddr_u addr;
498
0
  int on = 1;
499
0
  int err;
500
0
  char errbuf[100];
501
502
0
  addr.sa4.sin_family = AF_INET;
503
0
  addr.sa4.sin_port = htons(port);
504
0
  addr.sa4.sin_addr.s_addr= htonl(INADDR_ANY);
505
0
  sock = socket(AF_INET, SOCK_STREAM, 0);
506
0
  if (sock < 0) {
507
0
    if (EAFNOSUPPORT == errno) {
508
0
      msyslog(LOG_ERR, "NTSs: No IPv4 support, disabling NTS-KE listener");
509
0
      return true;
510
0
    }
511
0
    ntp_strerror_r(errno, errbuf, sizeof(errbuf));
512
0
    msyslog(LOG_ERR, "NTSs: Can't create socket4: %s", errbuf);
513
0
    return false;
514
0
  }
515
0
  err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
516
0
  if (0 > err) {
517
0
    ntp_strerror_r(errno, errbuf, sizeof(errbuf));
518
0
    msyslog(LOG_ERR, "NTSs: can't setsockopt4: %s", errbuf);
519
0
    close(sock);
520
0
    return false;
521
0
  }
522
0
  err = bind(sock, &addr.sa, sizeof(addr.sa4));
523
0
  if (0 > err) {
524
0
    ntp_strerror_r(errno, errbuf, sizeof(errbuf));
525
0
    msyslog(LOG_ERR, "NTSs: can't bind4: %s", errbuf);
526
0
    close(sock);
527
0
    return false;
528
0
  }
529
0
  if (listen(sock, 6) < 0) {
530
0
    ntp_strerror_r(errno, errbuf, sizeof(errbuf));
531
0
    msyslog(LOG_ERR, "NTSs: can't listen4: %s", errbuf);
532
0
    close(sock);
533
0
    return false;
534
0
  }
535
0
  msyslog(LOG_INFO, "NTSs: listen4 worked");
536
537
0
  listener4_sock = sock;
538
0
  return true;
539
0
}
540
541
0
bool create_listener6(int port) {
542
0
  int sock = -1;
543
0
  sockaddr_u addr;
544
0
  int on = 1;
545
0
  int err;
546
0
  char errbuf[100];
547
548
0
  addr.sa6.sin6_family = AF_INET6;
549
0
  addr.sa6.sin6_port = htons(port);
550
0
  addr.sa6.sin6_addr = in6addr_any;
551
0
  sock = socket(AF_INET6, SOCK_STREAM, 0);
552
0
  if (sock < 0) {
553
0
    if (EAFNOSUPPORT == errno) {
554
0
      msyslog(LOG_ERR, "NTSs: No IPv6 support, disabling NTS-KE listener");
555
0
      return true;
556
0
    }
557
0
    ntp_strerror_r(errno, errbuf, sizeof(errbuf));
558
0
    msyslog(LOG_ERR, "NTSs: Can't create socket6: %s", errbuf);
559
0
    return false;
560
0
  }
561
  /* Hack to keep IPV6 from listening on IPV4 too */
562
0
  err = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
563
0
  if (0 > err) {
564
0
    ntp_strerror_r(errno, errbuf, sizeof(errbuf));
565
0
    msyslog(LOG_ERR, "NTSs: can't setsockopt6only: %s", errbuf);
566
0
    close(sock);
567
0
    return false;
568
0
  }
569
0
  err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
570
0
  if (0 > err) {
571
0
    ntp_strerror_r(errno, errbuf, sizeof(errbuf));
572
0
    msyslog(LOG_ERR, "NTSs: can't setsockopt6: %s", errbuf);
573
0
    close(sock);
574
0
    return false;
575
0
  }
576
0
  err = bind(sock, &addr.sa, sizeof(addr.sa6));
577
0
  if (0 > err) {
578
0
    ntp_strerror_r(errno, errbuf, sizeof(errbuf));
579
0
    msyslog(LOG_ERR, "NTSs: can't bind6: %s", errbuf);
580
0
    close(sock);
581
0
    return false;
582
0
  }
583
0
  if (listen(sock, 6) < 0) {
584
0
    ntp_strerror_r(errno, errbuf, sizeof(errbuf));
585
0
    msyslog(LOG_ERR, "NTSs: can't listen6: %s", errbuf);
586
0
    close(sock);
587
0
    return false;
588
0
  }
589
0
  msyslog(LOG_INFO, "NTSs: listen6 worked");
590
591
0
  listener6_sock = sock;
592
0
  return true;
593
0
}
594
595
0
bool nts_ke_process_receive(struct BufCtl_t *buf, int *aead) {
596
0
  while (buf->left >= NTS_KE_HDR_LNG) {
597
0
    uint16_t type, data;
598
0
    int length;
599
0
    bool critical = false;
600
601
    // FIXME: msyslogs need rate limiting
602
0
    type = ke_next_record(buf, &length);
603
0
                if (length > buf->left){
604
0
                        msyslog(LOG_ERR, "NTSs: Chunk too big: 0x%x, %d, %d",
605
0
                                type, buf->left, length);
606
0
                        return false;
607
0
                }
608
0
    if (NTS_CRITICAL & type) {
609
0
      critical = true;
610
0
      type &= ~NTS_CRITICAL;
611
0
    }
612
0
    if (0) // Handy for debugging but very verbose
613
0
      msyslog(LOG_INFO, "NTSs: Record: T=%d, L=%d, C=%d", type, length, critical);
614
0
    switch (type) {
615
0
        case nts_error:
616
0
      if (sizeof(data) != length) {
617
0
        msyslog(LOG_ERR, "NTSs: wrong length on error: %d", length);
618
0
        return false;
619
0
      }
620
0
      data = next_uint16(buf);
621
0
      msyslog(LOG_ERR, "NTSs: error: %d", data);
622
0
      return false;
623
0
        case nts_next_protocol_negotiation:
624
0
      if (sizeof(data) != length) {
625
0
        msyslog(LOG_ERR, "NTSs: NPN-Wrong length: %d", length);
626
0
        return false;
627
0
      }
628
0
      data = next_uint16(buf);
629
0
      if (data != nts_protocol_NTP) {
630
0
        msyslog(LOG_ERR, "NTSs: NPN-Bad data: %d", data);
631
0
        return false;
632
0
      }
633
0
      break;
634
0
        case nts_algorithm_negotiation:
635
0
      if (buf->left < length || length % sizeof(uint16_t) > 0) {
636
0
        msyslog(LOG_ERR, "NTSs: AN-Wrong length: %d", length);
637
0
        return false;
638
0
      }
639
0
      for (int i=0; i<length; i+=sizeof(uint16_t)) {
640
0
        data = next_uint16(buf);
641
0
        if (0 == nts_get_key_length(data)) {
642
0
          if (0)  /* for debugging */
643
0
            msyslog(LOG_ERR, "NTSs: AN-Unsupported AEAN type: %d", data);
644
0
          continue;     /* ignore types we don't support */
645
0
        }
646
0
        if (*aead != NO_AEAD)
647
0
          continue;     /* already got one */
648
0
        *aead = data;   /* take this one */
649
0
      }
650
0
      break;
651
0
        case nts_end_of_message:
652
0
      if ((0 != length) || !critical) {
653
0
        msyslog(LOG_ERR, "NTSs: EOM-Wrong length or not Critical: %d, %d",
654
0
          length, critical);
655
0
        return false;
656
0
      }
657
0
      if (0 != buf->left) {
658
0
        msyslog(LOG_ERR, "NTSs: EOM not at end: %d", buf->left);
659
0
        return false;
660
0
      }
661
0
      break;
662
0
        default:
663
0
      msyslog(LOG_ERR, "NTSs: received strange type: T=%d, C=%d, L=%d",
664
0
        type, critical, length);
665
0
      if (critical) {
666
0
        return false;
667
0
      }
668
0
      buf->next += length;
669
0
      buf->left -= length;
670
0
      break;
671
0
    } /* case */
672
0
  }   /* while */
673
674
// FIXME: check for missing EOM.  Need to read more?
675
0
  if (buf->left > 0)
676
0
    return false;
677
678
0
  return true;
679
680
0
}
681
682
void nts_ke_setup_send(struct BufCtl_t *buf, int aead,
683
0
       uint8_t *c2s, uint8_t *s2c, int keylen) {
684
685
  /* 4.1.2 Next Protocol */
686
0
  ke_append_record_uint16(buf,
687
0
        NTS_CRITICAL+nts_next_protocol_negotiation, nts_protocol_NTP);
688
  /* 4.1.5 AEAD Algorithm List */
689
0
  ke_append_record_uint16(buf, nts_algorithm_negotiation, aead);
690
691
0
  if (extra_port)
692
0
          ke_append_record_uint16(buf, nts_port_negotiation, extra_port);
693
694
695
0
  for (int i=0; i<NTS_MAX_COOKIES; i++) {
696
0
    uint8_t cookie[NTS_MAX_COOKIELEN];
697
0
    int cookielen = nts_make_cookie(cookie, aead, c2s, s2c, keylen);
698
0
    ke_append_record_bytes(buf, nts_new_cookie, cookie, cookielen);
699
0
  }
700
701
  /* 4.1.1: End, Critical */
702
0
  ke_append_record_null(buf, NTS_CRITICAL+nts_end_of_message);
703
0
}
704
705
/* end */