Coverage Report

Created: 2026-08-31 07:01

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