...
 
Commits (17)
BUGS:
timeout on client connect too long (system default)
Is 3 seconds timeout OK? (both client and server)
nts_log_ssl_error() No SSL param ??
ERR_error_string_n
Fix SecondsPerDay in nts_cookie.c
Set to 3600 for testing
multithread msyslog
libntp/lib_strbuf.c too
libntp/lib_strbuf.c is used by socktoa and sockporttoa
strerror
documentation:
......
......@@ -14,10 +14,10 @@
#include "ntp_malloc.h"
typedef union {
struct sockaddr sa;
struct sockaddr_in sa4;
struct sockaddr_in6 sa6;
typedef union { /* On Linux, these come from: */
struct sockaddr sa; /* /usr/include/bits/socket.h */
struct sockaddr_in sa4; /* /usr/include/linux/in.h */
struct sockaddr_in6 sa6; /* /usr/include/linux/in6.h */
} sockaddr_u;
/*
......
......@@ -23,9 +23,63 @@ bool nts_server_init2(void); /* after sandbox */
bool nts_cookie_init2(void);
bool nts_read_cookie_keys(void);
bool nts_make_cookie_key(void);
bool nts_write_cookie_keys(void);
int nts_make_cookie(uint8_t *cookie,
uint16_t aead,
uint8_t *c2s, uint8_t *s2c, int keylen);
bool nts_unpack_cookie(uint8_t *cookie, int cookielen,
uint16_t *aead,
uint8_t *c2s, uint8_t *s2c, int *keylen);
/* working finger into a buffer - updated by append/unpack routines */
struct BufCtl_t {
uint8_t *next; /* pointer to next data/space */
int left; /* data left or space available */
};
typedef struct BufCtl_t BufCtl;
bool nts_ke_process_receive(struct BufCtl_t *buf, int *aead);
bool nts_ke_setup_send(struct BufCtl_t *buf, int aead,
uint8_t *c2s, uint8_t *s2c, int keylen);
/***********************************************************/
/* buffer packing/unpacking routines.
* NB: The length field in NTP extensions includes the header
* while the length field in NTS-KE data streams does not.
*
* These routines do not handle padding. NTS-KE has no padding.
* NTP extensions are padded to word (4 byte) boundaries.
*
* Note that data on the wire is big endian.
* buffer is wire format, not host format.
*/
/* xxx_append_record_foo makes whole record with one foo */
/* append_foo appends foo to existing partial record */
void ke_append_record_null(BufCtl* buf, uint16_t type);
void ke_append_record_uint16(BufCtl* buf, uint16_t type, uint16_t data);
void ke_append_record_bytes(BufCtl* buf, uint16_t type, uint8_t *data, int length);
void ex_append_record_null(BufCtl* buf, uint16_t type);
void ex_append_record_uint16(BufCtl* buf, uint16_t type, uint16_t data);
void ex_append_record_bytes(BufCtl* buf, uint16_t type, uint8_t *data, int length);
void ex_append_header(BufCtl* buf, uint16_t type, uint16_t length);
void append_header(BufCtl* buf, uint16_t type, uint16_t length);
void append_uint16(BufCtl* buf, uint16_t data);
void append_bytes(BufCtl* buf, uint8_t *data, int length);
uint16_t ke_next_record(BufCtl* buf, int *length);
uint16_t ex_next_record(BufCtl* buf, int *length); /* body length */
uint16_t next_uint16(BufCtl* buf);
uint16_t next_bytes(BufCtl* buf, uint8_t *data, int length);
/***********************************************************/
#define NTS_MAX_KEYLEN 64 /* used in cookies */
#define NTS_MAX_COOKIELEN 192 /* see nts_cookie.c */
......
/*
* nts2.h - NTS (Network Time Security) declarations
* other half of nts.h which doesn't include openssl/ssh.h
* This split helps test routines.
*/
#ifndef GUARD_NTS2_H
#define GUARD_NTS2_H
......@@ -9,11 +10,16 @@
#include <stdint.h>
#include <openssl/ssl.h>
#include "nts.h"
bool nts_load_certificate(SSL_CTX *ctx);
bool nts_load_ciphers(SSL_CTX *ctx);
bool nts_load_versions(SSL_CTX *ctx);
int nts_ssl_read(SSL *ssl, uint8_t *buff, int buff_length);
int nts_ssl_write(SSL *ssl, uint8_t *buff, int buff_length);
void nts_log_ssl_error(void);
int nts_get_key_length(uint16_t aead);
......@@ -23,53 +29,5 @@ uint16_t nts_string_to_aead(const char* text);
bool nts_make_keys(SSL *ssl, uint16_t aead,
uint8_t *c2s, uint8_t *s2c, int keylen);
int nts_make_cookie(uint8_t *cookie,
uint16_t aead,
uint8_t *c2s, uint8_t *s2c, int keylen);
bool nts_unpack_cookie(uint8_t *cookie, int cookielen,
uint16_t *aead,
uint8_t *c2s, uint8_t *s2c, int *keylen);
/* buffer packing/unpacking routines.
* NB: The length field in NTP extensions includes the header
* while the length field in NTS-KE data streams does not.
*
* These routines do not handle padding. NTS-KE has no padding.
* NTP extensions are padded to word (4 byte) boundaries.
*
* Note that data on the wire is big endian.
* buffer is wire format, not host format.
*/
/* working finger into a buffer - updated by append/unpack routines */
struct BufCtl_t {
uint8_t *next; /* pointer to next data/space */
int left; /* data left or space available */
};
typedef struct BufCtl_t BufCtl;
/* xxx_append_record_foo makes whole record with one foo */
/* append_foo appends foo to existing partial record */
void ke_append_record_null(BufCtl* buf, uint16_t type);
void ke_append_record_uint16(BufCtl* buf, uint16_t type, uint16_t data);
void ke_append_record_bytes(BufCtl* buf, uint16_t type, uint8_t *data, int length);
void ex_append_record_null(BufCtl* buf, uint16_t type);
void ex_append_record_uint16(BufCtl* buf, uint16_t type, uint16_t data);
void ex_append_record_bytes(BufCtl* buf, uint16_t type, uint8_t *data, int length);
void ex_append_header(BufCtl* buf, uint16_t type, uint16_t length);
void append_header(BufCtl* buf, uint16_t type, uint16_t length);
void append_uint16(BufCtl* buf, uint16_t data);
void append_bytes(BufCtl* buf, uint8_t *data, int length);
uint16_t ke_next_record(BufCtl* buf, int *length);
uint16_t ex_next_record(BufCtl* buf, int *length); /* body length */
uint16_t next_uint16(BufCtl* buf);
uint16_t next_bytes(BufCtl* buf, uint8_t *data, int length);
#endif /* GUARD_NTS2_H */
......@@ -39,25 +39,25 @@ uint32_t ntp_syslogmask = INIT_NTP_SYSLOGMASK;
extern char * progname;
/* Declare the local functions */
const char * humanlogtime(void);
#define TIMESTAMP_LEN 128
static void humanlogtime(char buf[TIMESTAMP_LEN]);
static void addto_syslog (int, const char *);
/* We don't want to clutter up the log with the year and day of the week,
etc.; just the minimal date and time. */
const char *
humanlogtime(void)
static void
humanlogtime(char buf[TIMESTAMP_LEN])
{
char * bp;
time_t cursec;
struct tm tmbuf, *tm;
cursec = time(NULL);
tm = localtime_r(&cursec, &tmbuf);
if (!tm)
return "-- --- --:--:--";
bp = lib_getbuf();
if (!tm) {
strlcpy(buf, "-- --- --:--:--", TIMESTAMP_LEN);
return;
}
#ifdef ENABLE_CLASSIC_MODE
const char * const months[12] = {
......@@ -65,17 +65,15 @@ humanlogtime(void)
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
snprintf(bp, LIB_BUFLENGTH, "%2d %s %02d:%02d:%02d",
snprintf(buf, TIMESTAMP_LEN, "%2d %s %02d:%02d:%02d",
tm->tm_mday, months[tm->tm_mon],
tm->tm_hour, tm->tm_min, tm->tm_sec);
#else
/* ISO 8601 is a better format, sort order equals time order */
snprintf(bp, LIB_BUFLENGTH, "%04d-%02d-%02dT%02d:%02d:%02d",
snprintf(buf, TIMESTAMP_LEN, "%04d-%02d-%02dT%02d:%02d:%02d",
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
#endif /* ENABLE_CLASSIC_MODE */
return bp;
}
......@@ -100,6 +98,7 @@ addto_syslog(
int pid;
const char * nl_or_empty;
const char * human_time;
char tbuf[TIMESTAMP_LEN];
/* setup program basename static var prog if needed */
if (progname != prevcall_progname) {
......@@ -126,9 +125,10 @@ addto_syslog(
return;
/* syslog() adds the timestamp, name, and pid */
if (msyslog_include_timestamp)
human_time = humanlogtime();
else /* suppress gcc pot. uninit. warning */
if (msyslog_include_timestamp) {
humanlogtime(tbuf);
human_time = tbuf;
} else /* suppress gcc pot. uninit. warning */
human_time = NULL;
if (termlogit_pid || log_to_file)
pid = getpid();
......@@ -154,11 +154,23 @@ addto_syslog(
}
if (log_to_file) {
/*
* Thread-safe write, the de-facto way. It's not
* actually guaranteed by standards that a write of
* PIPE_BUF chars or less is atomic anywhere but on a
* pipe. In ancient times this was 512 and happened to
* be equal to the usual size of a hardware disk sector,
* which was what really bounded atomicity. The actual
* answer under POSIX is SSIZE_MAX, which is far larger
* than we want or need to allocate here.
*/
char buf[PIPE_BUF];
buf[0] = '\0';
if (msyslog_include_timestamp)
fprintf(syslog_file, "%s ", human_time);
fprintf(syslog_file, "%s[%d]: %s%s", prog, pid, msg,
nl_or_empty);
fflush(syslog_file);
snprintf(buf, sizeof(buf), "%s ", human_time);
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf) - 1,
"%s[%d]: %s%s", prog, pid, msg, nl_or_empty);
IGNORE(write(fileno(syslog_file), buf, strlen(buf)));
}
}
......
......@@ -14,6 +14,7 @@ ntpviz [-d LOGDIR]
[-p DAYS]
[-s starttime]
[-w SIZE | --width SIZE]
[-T terminal]
[--all-peer-jitters |
--all-peer-offsets |
--local-error |
......@@ -1453,7 +1454,7 @@ Python by ESR, concept and gnuplot code by Dan Drown.
choices=['s', 'm', 'l'],
default='m',
dest='width',
help="PNG width: s, m, or l",
help="Image width: s, m, or l",
type=str)
group.add_argument('--all-peer-jitters',
action="store_true",
......
......@@ -121,6 +121,12 @@ bool nts_load_versions(SSL_CTX *ctx) {
maxver = nts_translate_version(ntsconfig.maxtls);
if ((-1 == minver) || (-1 == maxver))
return false;
#if (OPENSSL_VERSION_NUMBER == 0x1010101fL)
if (0 == maxver) {
msyslog(LOG_INFO, "NTS: Using TLS1.2 to avoid bug in OpenSSL 1.1.1a.");
maxver = TLS1_2_VERSION;
}
#endif
#if (OPENSSL_VERSION_NUMBER > 0x1010000fL)
if(0 == minver) minver = TLS1_2_VERSION; // 3.
SSL_CTX_set_min_proto_version(ctx, minver);
......@@ -199,6 +205,28 @@ bool nts_load_certificate(SSL_CTX *ctx) {
}
int nts_ssl_read(SSL *ssl, uint8_t *buff, int buff_length) {
int bytes_read;
bytes_read = SSL_read(ssl, buff, buff_length);
if (0 >= bytes_read) {
msyslog(LOG_INFO, "NTS: SSL_read error: %s", strerror(errno));
nts_log_ssl_error();
return -1;
}
return bytes_read;
}
int nts_ssl_write(SSL *ssl, uint8_t *buff, int buff_length) {
int bytes_written;
bytes_written = SSL_write(ssl, buff, buff_length);
if (0 >= bytes_written) {
msyslog(LOG_INFO, "NTS: SSL_write error: %s", strerror(errno));
nts_log_ssl_error();
return -1;
}
return bytes_written;
}
void nts_log_ssl_error(void) {
char buff[256];
int err = ERR_get_error();
......
......@@ -27,11 +27,12 @@
#include "nts2.h"
#include "ntp_dns.h"
int open_TCP_socket(struct peer* peer);
int open_TCP_socket(struct peer *peer, const char *hostname);
bool nts_set_cert_search(SSL_CTX *ctx);
bool check_certificate(struct peer* peer, SSL *ssl);
bool nts_client_send_request(struct peer* peer, SSL *ssl);
bool nts_client_process_response(struct peer* peer, SSL *ssl);
void set_hostname(SSL *ssl, const char *hostname);
bool check_certificate(SSL *ssl, struct peer *peer);
bool nts_client_send_request(SSL *ssl, struct peer *peer);
bool nts_client_process_response(SSL *ssl, struct peer *peer);
bool nts_server_lookup(char *server, sockaddr_u *addr);
static SSL_CTX *client_ctx = NULL;
......@@ -90,6 +91,8 @@ bool nts_client_init(void) {
bool nts_probe(struct peer * peer) {
struct timeval timeout = {.tv_sec = NTS_KE_TIMEOUT, .tv_usec = 0};
const char *hostname = peer->hostname;
char hostbuf[100];
SSL *ssl;
int server;
l_fp start, finish;
......@@ -102,7 +105,23 @@ bool nts_probe(struct peer * peer) {
addrOK = false;
get_systime(&start);
server = open_TCP_socket(peer);
if (NULL == hostname) {
/* IP Address case */
int af = AF(&peer->srcadr);
switch (af) {
case AF_INET:
inet_ntop(af, PSOCK_ADDR4(&peer->srcadr), hostbuf, sizeof(hostbuf));
break;
case AF_INET6:
inet_ntop(af, PSOCK_ADDR6(&peer->srcadr), hostbuf, sizeof(hostbuf));
break;
default:
return false;
}
hostname = hostbuf;
}
server = open_TCP_socket(peer, hostname);
if (-1 == server) {
nts_ke_probes_bad++;
return false;
......@@ -121,6 +140,7 @@ bool nts_probe(struct peer * peer) {
// Ugly since most SSL routines return 1 on success.
ssl = SSL_new(client_ctx);
set_hostname(ssl, hostname);
SSL_set_fd(ssl, server);
if (1 != SSL_connect(ssl)) {
......@@ -140,12 +160,12 @@ bool nts_probe(struct peer * peer) {
SSL_get_cipher_name(ssl),
SSL_get_cipher_bits(ssl, NULL));
if (!check_certificate(peer, ssl))
if (!check_certificate(ssl, peer))
goto bail;
if (!nts_client_send_request(peer, ssl))
if (!nts_client_send_request(ssl, peer))
goto bail;
if (!nts_client_process_response(peer, ssl))
if (!nts_client_process_response(ssl, peer))
goto bail;
/* We are using AEAD_AES_SIV_CMAC_xxx, from RFC 5297
......@@ -155,17 +175,20 @@ bool nts_probe(struct peer * peer) {
msyslog(LOG_ERR, "NTSc: Unknown AEAD code: %d", peer->nts_state.aead);
goto bail;
}
nts_make_keys(ssl,
peer->nts_state.aead,
peer->nts_state.c2s,
peer->nts_state.s2c,
peer->nts_state.keylen);
if (!nts_make_keys(ssl,
peer->nts_state.aead,
peer->nts_state.c2s,
peer->nts_state.s2c,
peer->nts_state.keylen))
goto bail;
addrOK = true;
bail:
if (!addrOK)
if (!addrOK) {
nts_ke_probes_bad++;
peer->nts_state.count = -1;
}
SSL_shutdown(ssl);
SSL_free(ssl);
close(server);
......@@ -173,7 +196,7 @@ bail:
get_systime(&finish);
finish -= start;
msyslog(LOG_INFO, "NTSc: NTS-KE req to %s took %.3Lf sec, %s",
peer->hostname, lfptod(finish),
hostname, lfptod(finish),
addrOK? "OK" : "fail");
return addrOK;
......@@ -189,7 +212,7 @@ bool nts_check(struct peer *peer) {
return addrOK;
}
int open_TCP_socket(struct peer *peer) {
int open_TCP_socket(struct peer *peer, const char *hostname) {
char host[256], port[32];
char *tmp;
struct addrinfo hints;
......@@ -199,12 +222,9 @@ int open_TCP_socket(struct peer *peer) {
l_fp start, finish;
/* copy avoids dancing around const warnings */
strlcpy(host, peer->hostname, sizeof(host));
strlcpy(host, hostname, sizeof(host));
ZERO(hints);
hints.ai_protocol = IPPROTO_TCP;
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF(&peer->srcadr);
/* handle xxx:port case */
tmp = strchr(host, ']');
if (NULL == tmp) {
tmp = strchr(host, ':');
......@@ -221,17 +241,21 @@ int open_TCP_socket(struct peer *peer) {
strlcpy(port, tmp, sizeof(port));
}
ZERO(hints);
hints.ai_protocol = IPPROTO_TCP;
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF(&peer->srcadr); /* -4, -6 switch */
get_systime(&start);
gai_rc = getaddrinfo(host, port, &hints, &answer);
if (0 != gai_rc) {
msyslog(LOG_INFO, "NTSc: nts_probe: DNS error trying to contact %s: %d, %s",
peer->hostname, gai_rc, gai_strerror(gai_rc));
hostname, gai_rc, gai_strerror(gai_rc));
return -1;
}
get_systime(&finish);
finish -= start;
msyslog(LOG_INFO, "NTSc: DNS lookup of %s took %.3Lf sec",
peer->hostname, lfptod(finish));
hostname, lfptod(finish));
/* Save first answer for NTP */
memcpy(&sockaddr, answer->ai_addr, answer->ai_addrlen);
......@@ -256,12 +280,11 @@ int open_TCP_socket(struct peer *peer) {
return sockfd;
}
bool check_certificate(struct peer* peer, SSL *ssl) {
X509 *cert = SSL_get_peer_certificate(ssl);
void set_hostname(SSL *ssl, const char *hostname) {
char host[256], *tmp;
/* chop off trailing :port */
strlcpy(host, peer->hostname, sizeof(host));
strlcpy(host, hostname, sizeof(host));
tmp = strchr(host, ']');
if (NULL == tmp)
tmp = host; /* not IPv6 [...] format */
......@@ -272,6 +295,7 @@ bool check_certificate(struct peer* peer, SSL *ssl) {
// https://wiki.openssl.org/index.php/Hostname_validation
#if (OPENSSL_VERSION_NUMBER > 0x1010000fL)
SSL_set1_host(ssl, host);
msyslog(LOG_DEBUG, "NTSc: set cert host: %s", host);
#elif (OPENSSL_VERSION_NUMBER > 0x1000200fL)
{
X509_VERIFY_PARAM *param = SSL_get0_param(ssl);
......@@ -281,9 +305,15 @@ bool check_certificate(struct peer* peer, SSL *ssl) {
SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
}
#else
UNUSED_ARG(ssl);
msyslog(LOG_ERR, "NTSc: can't check hostname/certificate");
#endif
}
bool check_certificate(SSL *ssl, struct peer* peer) {
X509 *cert = SSL_get_peer_certificate(ssl);
if (NULL == cert) {
msyslog(LOG_INFO, "NTSc: No certificate");
if (!(FLAG_NTS_NOVAL & peer->cfg.flags))
......@@ -299,6 +329,7 @@ bool check_certificate(struct peer* peer, SSL *ssl) {
certname = X509_get_issuer_name(cert);
X509_NAME_oneline(certname, name, sizeof(name));
msyslog(LOG_INFO, "NTSc: certificate issuer name: %s", name);
X509_free(cert);
certok = SSL_get_verify_result(ssl);
if (X509_V_OK == certok) {
msyslog(LOG_INFO, "NTSc: certificate is valid.");
......@@ -309,6 +340,9 @@ bool check_certificate(struct peer* peer, SSL *ssl) {
return false;
}
}
#if (OPENSSL_VERSION_NUMBER > 0x1010000fL)
msyslog(LOG_DEBUG, "NTSc: matched cert host: %s", SSL_get0_peername(ssl));
#endif
return true;
}
......@@ -343,7 +377,7 @@ bool nts_make_keys(SSL *ssl, uint16_t aead, uint8_t *c2s, uint8_t *s2c, int keyl
return true;
}
bool nts_client_send_request(struct peer* peer, SSL *ssl) {
bool nts_client_send_request(SSL *ssl, struct peer* peer) {
uint8_t buff[1000];
int used, transferred;
struct BufCtl_t buf;
......@@ -375,26 +409,22 @@ bool nts_client_send_request(struct peer* peer, SSL *ssl) {
used, (long)sizeof(buff), strerror(errno));
return false;
}
transferred = SSL_write(ssl, buff, used);
if (used != transferred) {
msyslog(LOG_ERR, "NTSc: write failed: %d, %d, %s", used, transferred, strerror(errno));
nts_log_ssl_error();
transferred = nts_ssl_write(ssl, buff, used);
if (used != transferred)
return false;
}
return true;
}
bool nts_client_process_response(struct peer* peer, SSL *ssl) {
bool nts_client_process_response(SSL *ssl, struct peer* peer) {
uint8_t buff[2048]; /* RFC 4. says SHOULD be 65K */
int transferred, idx;
struct BufCtl_t buf;
transferred = SSL_read(ssl, buff, sizeof(buff));
if (0 > transferred) {
msyslog(LOG_ERR, "NTSc: read failed: %d, %s", transferred, strerror(errno));
nts_log_ssl_error();
transferred = nts_ssl_read(ssl, buff, sizeof(buff));
if (0 > transferred)
return false;
}
msyslog(LOG_ERR, "NTSc: read %d bytes", transferred);
peer->nts_state.aead = NO_AEAD;
......
......@@ -64,11 +64,6 @@
* 168
*/
bool nts_read_cookie_keys(void);
bool nts_make_cookie_key(void);
bool nts_write_cookie_keys(void);
/* cookies use same AEAD algorithms as wire */
/* This determines which algorithm we use.
* Valid choices are 32, 48, and 64
......@@ -354,6 +349,7 @@ bool nts_unpack_cookie(uint8_t *cookie, int cookielen,
cipherlength = cookielen - AD_LENGTH;
plainlength = NTS_MAX_COOKIELEN;
// FIXME - needs lock
ok = AES_SIV_Decrypt(cookie_ctx,
plaintext, &plainlength,
key, K_length,
......
......@@ -25,7 +25,6 @@
static int create_listener(int port, int family);
static void* nts_ke_listener(void*);
static bool nts_ke_request(SSL *ssl);
static bool nts_ke_do_receive(SSL *ssl, int *aead);
static SSL_CTX *server_ctx = NULL;
......@@ -109,13 +108,13 @@ void* nts_ke_listener(void* arg) {
int sock = *(int*)arg;
while(1) {
struct sockaddr addr;
sockaddr_u addr;
uint len = sizeof(addr);
SSL *ssl;
l_fp start, finish;
int err;
int client, err;
int client = accept(sock, &addr, &len);
client = accept(sock, &addr.sa, &len);
if (client < 0) {
msyslog(LOG_ERR, "NTSs: TCP accept failed: %s", strerror(errno));
if (EBADF == errno)
......@@ -123,7 +122,7 @@ void* nts_ke_listener(void* arg) {
sleep(1); /* avoid log clutter on bug */
continue;
}
nts_ke_serves++;
nts_ke_serves++;
get_systime(&start);
msyslog(LOG_INFO, "NTSs: TCP accept-ed from %s",
sockporttoa((sockaddr_u *)&addr));
......@@ -172,19 +171,25 @@ return NULL;
}
bool nts_ke_request(SSL *ssl) {
/* Our cookies can be 104, 136, or 168 for AES_SIV_CMAC_xxx
/* RFC 4: servers must accept 1024
* Our cookies can be 104, 136, or 168 for AES_SIV_CMAC_xxx
* 8*168 fits comfortably into 2K.
*/
uint8_t buff[2048];
int bytes_written;
uint8_t c2s[NTS_MAX_KEYLEN], s2c[NTS_MAX_KEYLEN];
uint8_t cookie[NTS_MAX_COOKIELEN];
int aead, keylen, cookielen;
int aead, keylen;
struct BufCtl_t buf;
int bytes_read, bytes_written;
int used;
bytes_read = nts_ssl_read(ssl, buff, sizeof(buff));
if (0 > bytes_read)
return false;
buf.next = buff;
buf.left = bytes_read;
aead = NO_AEAD;
if (!nts_ke_do_receive(ssl, &aead))
if (!nts_ke_process_receive(&buf, &aead))
return false;
if ((NO_AEAD == aead) && (NULL != ntsconfig.aead))
......@@ -192,33 +197,22 @@ bool nts_ke_request(SSL *ssl) {
if (NO_AEAD == aead)
aead = AEAD_AES_SIV_CMAC_256; /* default */
buf.next = buff;
buf.left = sizeof(buff);
keylen = nts_get_key_length(aead);
nts_make_keys(ssl, aead, c2s, s2c, keylen);
/* 4.1.2 Next Protocol, 0 for NTP */
ke_append_record_uint16(&buf, NTS_CRITICAL+nts_next_protocol_negotiation, 0);
/* 4.1.5 AEAD Algorithm List */
ke_append_record_uint16(&buf, nts_algorithm_negotiation, aead);
if (!nts_make_keys(ssl, aead, c2s, s2c, keylen))
return false;
for (int i=0; i<NTS_MAX_COOKIES; i++) {
cookielen = nts_make_cookie(cookie, aead, c2s, s2c, keylen);
ke_append_record_bytes(&buf, nts_new_cookie, cookie, cookielen);
}
buf.next = buff;
buf.left = sizeof(buff);
if (!nts_ke_setup_send(&buf, aead, c2s, s2c, keylen))
return false;
/* 4.1.1: End, Critical */
ke_append_record_null(&buf, NTS_CRITICAL+nts_end_of_message);
used = sizeof(buff)-buf.left;
bytes_written = SSL_write(ssl, buff, used);
if (bytes_written != used) {
msyslog(LOG_INFO, "NTSs: SSL_write error: %s", strerror(errno));
nts_log_ssl_error();
bytes_written = nts_ssl_write(ssl, buff, used);
if (bytes_written != used)
return false;
}
msyslog(LOG_INFO, "NTSs: Returned %d bytes", bytes_written);
msyslog(LOG_INFO, "NTSs: Read %d, wrote %d bytes. AEAD=%d",
bytes_read, bytes_written, aead);
return true;
}
......@@ -289,7 +283,7 @@ int create_listener(int port, int family) {
}
if (listen(sock, 6) < 0) {
msyslog(LOG_ERR, "NTSs: can't listen6: %s", strerror(errno));
close(sock);
close(sock);
return -1;
}
msyslog(LOG_INFO, "NTSs: listen6 worked");
......@@ -301,27 +295,13 @@ int create_listener(int port, int family) {
return sock;
}
bool nts_ke_do_receive(SSL *ssl, int *aead) {
/* RFC 4: servers must accept 1024 */
uint8_t buff[1024];
int bytes_read;
struct BufCtl_t buf;
bytes_read = SSL_read(ssl, buff, sizeof(buff));
if (0 >= bytes_read) {
msyslog(LOG_INFO, "NTSs: SSL_read error: %s", strerror(errno));
nts_log_ssl_error();
return false;
}
buf.next = buff;
buf.left = bytes_read;
while (buf.left > 0) {
bool nts_ke_process_receive(struct BufCtl_t *buf, int *aead) {
while (buf->left > 0) {
uint16_t type, data;
int length;
bool critical = false;
type = ke_next_record(&buf, &length);
type = ke_next_record(buf, &length);
if (NTS_CRITICAL & type) {
critical = true;
type &= ~NTS_CRITICAL;
......@@ -330,13 +310,13 @@ bool nts_ke_do_receive(SSL *ssl, int *aead) {
msyslog(LOG_ERR, "NTSs: Record: T=%d, L=%d, C=%d", type, length, critical);
switch (type) {
case nts_error:
data = next_uint16(&buf);
data = next_uint16(buf);
if (sizeof(data) != length)
msyslog(LOG_ERR, "NTSs: wrong length on error: %d", length);
msyslog(LOG_ERR, "NTSs: error: %d", data);
return false;
case nts_next_protocol_negotiation:
data = next_uint16(&buf);
data = next_uint16(buf);
if ((sizeof(data) != length) || (data != 0)) {
msyslog(LOG_ERR, "NTSs: NPN-Wrong length or bad data: %d, %d",
length, data);
......@@ -345,7 +325,7 @@ bool nts_ke_do_receive(SSL *ssl, int *aead) {
break;
case nts_algorithm_negotiation:
for (int i=0; i<length; i+=sizeof(uint16_t)) {
data = next_uint16(&buf);
data = next_uint16(buf);
if (0 == nts_get_key_length(data)) {
if (0) /* for debugging */
msyslog(LOG_ERR, "NTSs: AN-Unsupported AEAN type: %d", data);
......@@ -362,8 +342,8 @@ bool nts_ke_do_receive(SSL *ssl, int *aead) {
length, critical);
return false;
}
if (0 != buf.left) {
msyslog(LOG_ERR, "NTSs: EOM not at end: %d", buf.left);
if (0 != buf->left) {
msyslog(LOG_ERR, "NTSs: EOM not at end: %d", buf->left);
return false;
}
break;
......@@ -371,8 +351,8 @@ bool nts_ke_do_receive(SSL *ssl, int *aead) {
msyslog(LOG_ERR, "NTSs: received strange type: T=%d, C=%d, L=%d",
type, critical, length);
if (critical) return false;
buf.next += length;
buf.left -= length;
buf->next += length;
buf->left -= length;
break;
} /* case */
} /* while */
......@@ -381,4 +361,26 @@ bool nts_ke_do_receive(SSL *ssl, int *aead) {
}
bool nts_ke_setup_send(struct BufCtl_t *buf, int aead,
uint8_t *c2s, uint8_t *s2c, int keylen) {
uint8_t cookie[NTS_MAX_COOKIELEN];
int cookielen;
/* 4.1.2 Next Protocol, 0 for NTP */
ke_append_record_uint16(buf, NTS_CRITICAL+nts_next_protocol_negotiation, 0);
/* 4.1.5 AEAD Algorithm List */
ke_append_record_uint16(buf, nts_algorithm_negotiation, aead);
for (int i=0; i<NTS_MAX_COOKIES; i++) {
cookielen = nts_make_cookie(cookie, aead, c2s, s2c, keylen);
ke_append_record_bytes(buf, nts_new_cookie, cookie, cookielen);
}
/* 4.1.1: End, Critical */
ke_append_record_null(buf, NTS_CRITICAL+nts_end_of_message);
return true;
}
/* end */