nts: allow multiple server keys and certificates
Allow the ntsservercert and ntsserverkey directives to be specified multiple times to enable the NTS-KE server to operate under multiple names.
This commit is contained in:
parent
80e627c86b
commit
90557cf1ba
8 changed files with 73 additions and 40 deletions
48
conf.c
48
conf.c
|
@ -76,6 +76,7 @@ static void parse_log(char *);
|
||||||
static void parse_mailonchange(char *);
|
static void parse_mailonchange(char *);
|
||||||
static void parse_makestep(char *);
|
static void parse_makestep(char *);
|
||||||
static void parse_maxchange(char *);
|
static void parse_maxchange(char *);
|
||||||
|
static void parse_ntsserver(char *, ARR_Instance files);
|
||||||
static void parse_ratelimit(char *line, int *enabled, int *interval,
|
static void parse_ratelimit(char *line, int *enabled, int *interval,
|
||||||
int *burst, int *leak);
|
int *burst, int *leak);
|
||||||
static void parse_refclock(char *);
|
static void parse_refclock(char *);
|
||||||
|
@ -252,8 +253,8 @@ static char *user;
|
||||||
/* NTS server and client configuration */
|
/* NTS server and client configuration */
|
||||||
static char *nts_dump_dir = NULL;
|
static char *nts_dump_dir = NULL;
|
||||||
static char *nts_ntp_server = NULL;
|
static char *nts_ntp_server = NULL;
|
||||||
static char *nts_server_cert_file = NULL;
|
static ARR_Instance nts_server_cert_files; /* array of (char *) */
|
||||||
static char *nts_server_key_file = NULL;
|
static ARR_Instance nts_server_key_files; /* array of (char *) */
|
||||||
static int nts_server_port = NKE_PORT;
|
static int nts_server_port = NKE_PORT;
|
||||||
static int nts_server_processes = 1;
|
static int nts_server_processes = 1;
|
||||||
static int nts_server_connections = 100;
|
static int nts_server_connections = 100;
|
||||||
|
@ -388,6 +389,9 @@ CNF_Initialise(int r, int client_only)
|
||||||
ntp_restrictions = ARR_CreateInstance(sizeof (AllowDeny));
|
ntp_restrictions = ARR_CreateInstance(sizeof (AllowDeny));
|
||||||
cmd_restrictions = ARR_CreateInstance(sizeof (AllowDeny));
|
cmd_restrictions = ARR_CreateInstance(sizeof (AllowDeny));
|
||||||
|
|
||||||
|
nts_server_cert_files = ARR_CreateInstance(sizeof (char *));
|
||||||
|
nts_server_key_files = ARR_CreateInstance(sizeof (char *));
|
||||||
|
|
||||||
rtc_device = Strdup(DEFAULT_RTC_DEVICE);
|
rtc_device = Strdup(DEFAULT_RTC_DEVICE);
|
||||||
hwclock_file = Strdup(DEFAULT_HWCLOCK_FILE);
|
hwclock_file = Strdup(DEFAULT_HWCLOCK_FILE);
|
||||||
user = Strdup(DEFAULT_USER);
|
user = Strdup(DEFAULT_USER);
|
||||||
|
@ -426,6 +430,10 @@ CNF_Finalise(void)
|
||||||
Free(((RefclockParameters *)ARR_GetElement(refclock_sources, i))->driver_name);
|
Free(((RefclockParameters *)ARR_GetElement(refclock_sources, i))->driver_name);
|
||||||
Free(((RefclockParameters *)ARR_GetElement(refclock_sources, i))->driver_parameter);
|
Free(((RefclockParameters *)ARR_GetElement(refclock_sources, i))->driver_parameter);
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < ARR_GetSize(nts_server_cert_files); i++)
|
||||||
|
Free(*(char **)ARR_GetElement(nts_server_cert_files, i));
|
||||||
|
for (i = 0; i < ARR_GetSize(nts_server_key_files); i++)
|
||||||
|
Free(*(char **)ARR_GetElement(nts_server_key_files, i));
|
||||||
|
|
||||||
ARR_DestroyInstance(init_sources);
|
ARR_DestroyInstance(init_sources);
|
||||||
ARR_DestroyInstance(ntp_sources);
|
ARR_DestroyInstance(ntp_sources);
|
||||||
|
@ -437,6 +445,9 @@ CNF_Finalise(void)
|
||||||
ARR_DestroyInstance(ntp_restrictions);
|
ARR_DestroyInstance(ntp_restrictions);
|
||||||
ARR_DestroyInstance(cmd_restrictions);
|
ARR_DestroyInstance(cmd_restrictions);
|
||||||
|
|
||||||
|
ARR_DestroyInstance(nts_server_cert_files);
|
||||||
|
ARR_DestroyInstance(nts_server_key_files);
|
||||||
|
|
||||||
Free(drift_file);
|
Free(drift_file);
|
||||||
Free(dumpdir);
|
Free(dumpdir);
|
||||||
Free(hwclock_file);
|
Free(hwclock_file);
|
||||||
|
@ -457,8 +468,6 @@ CNF_Finalise(void)
|
||||||
Free(tempcomp_point_file);
|
Free(tempcomp_point_file);
|
||||||
Free(nts_dump_dir);
|
Free(nts_dump_dir);
|
||||||
Free(nts_ntp_server);
|
Free(nts_ntp_server);
|
||||||
Free(nts_server_cert_file);
|
|
||||||
Free(nts_server_key_file);
|
|
||||||
Free(nts_trusted_cert_file);
|
Free(nts_trusted_cert_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,9 +668,9 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
||||||
} else if (!strcasecmp(command, "ntsrotate")) {
|
} else if (!strcasecmp(command, "ntsrotate")) {
|
||||||
parse_int(p, &nts_rotate);
|
parse_int(p, &nts_rotate);
|
||||||
} else if (!strcasecmp(command, "ntsservercert")) {
|
} else if (!strcasecmp(command, "ntsservercert")) {
|
||||||
parse_string(p, &nts_server_cert_file);
|
parse_ntsserver(p, nts_server_cert_files);
|
||||||
} else if (!strcasecmp(command, "ntsserverkey")) {
|
} else if (!strcasecmp(command, "ntsserverkey")) {
|
||||||
parse_string(p, &nts_server_key_file);
|
parse_ntsserver(p, nts_server_key_files);
|
||||||
} else if (!strcasecmp(command, "peer")) {
|
} else if (!strcasecmp(command, "peer")) {
|
||||||
parse_source(p, command, 1);
|
parse_source(p, command, 1);
|
||||||
} else if (!strcasecmp(command, "pidfile")) {
|
} else if (!strcasecmp(command, "pidfile")) {
|
||||||
|
@ -1158,6 +1167,17 @@ parse_mailonchange(char *line)
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_ntsserver(char *line, ARR_Instance files)
|
||||||
|
{
|
||||||
|
char *file = NULL;
|
||||||
|
|
||||||
|
parse_string(line, &file);
|
||||||
|
ARR_AppendElement(files, &file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
parse_allow_deny(char *line, ARR_Instance restrictions, int allow)
|
parse_allow_deny(char *line, ARR_Instance restrictions, int allow)
|
||||||
{
|
{
|
||||||
|
@ -2515,18 +2535,16 @@ CNF_GetNtsNtpServer(void)
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
char *
|
int
|
||||||
CNF_GetNtsServerCertFile(void)
|
CNF_GetNtsServerCertAndKeyFiles(const char ***certs, const char ***keys)
|
||||||
{
|
{
|
||||||
return nts_server_cert_file;
|
*certs = ARR_GetElements(nts_server_cert_files);
|
||||||
}
|
*keys = ARR_GetElements(nts_server_key_files);
|
||||||
|
|
||||||
/* ================================================== */
|
if (ARR_GetSize(nts_server_cert_files) != ARR_GetSize(nts_server_key_files))
|
||||||
|
LOG_FATAL("Uneven number of NTS certs and keys");
|
||||||
|
|
||||||
char *
|
return ARR_GetSize(nts_server_cert_files);
|
||||||
CNF_GetNtsServerKeyFile(void)
|
|
||||||
{
|
|
||||||
return nts_server_key_file;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
3
conf.h
3
conf.h
|
@ -153,8 +153,7 @@ extern int CNF_GetHwTsInterface(unsigned int index, CNF_HwTsInterface **iface);
|
||||||
|
|
||||||
extern char *CNF_GetNtsDumpDir(void);
|
extern char *CNF_GetNtsDumpDir(void);
|
||||||
extern char *CNF_GetNtsNtpServer(void);
|
extern char *CNF_GetNtsNtpServer(void);
|
||||||
extern char *CNF_GetNtsServerCertFile(void);
|
extern int CNF_GetNtsServerCertAndKeyFiles(const char ***certs, const char ***keys);
|
||||||
extern char *CNF_GetNtsServerKeyFile(void);
|
|
||||||
extern int CNF_GetNtsServerPort(void);
|
extern int CNF_GetNtsServerPort(void);
|
||||||
extern int CNF_GetNtsServerProcesses(void);
|
extern int CNF_GetNtsServerProcesses(void);
|
||||||
extern int CNF_GetNtsServerConnections(void);
|
extern int CNF_GetNtsServerConnections(void);
|
||||||
|
|
|
@ -1567,10 +1567,16 @@ The port will be open only when a certificate and key is specified by the
|
||||||
[[ntsservercert]]*ntsservercert* _file_::
|
[[ntsservercert]]*ntsservercert* _file_::
|
||||||
This directive specifies a file containing a certificate in the PEM format
|
This directive specifies a file containing a certificate in the PEM format
|
||||||
for *chronyd* to operate as an NTS server.
|
for *chronyd* to operate as an NTS server.
|
||||||
|
+
|
||||||
|
This directive can be used multiple times to specify multiple certificates.
|
||||||
|
|
||||||
[[ntsserverkey]]*ntsserverkey* _file_::
|
[[ntsserverkey]]*ntsserverkey* _file_::
|
||||||
This directive specifies a file containing a private key in the PEM format
|
This directive specifies a file containing a private key in the PEM format
|
||||||
for *chronyd* to operate as an NTS server.
|
for *chronyd* to operate as an NTS server.
|
||||||
|
+
|
||||||
|
This directive can be used multiple times to specify multiple keys. The number
|
||||||
|
of keys must be the same as the number of certificates and the corresponding
|
||||||
|
files must be specified in the same order.
|
||||||
|
|
||||||
[[ntsprocesses]]*ntsprocesses* _processes_::
|
[[ntsprocesses]]*ntsprocesses* _processes_::
|
||||||
This directive specifies how many helper processes will *chronyd* operating
|
This directive specifies how many helper processes will *chronyd* operating
|
||||||
|
|
|
@ -678,13 +678,14 @@ void
|
||||||
NKS_PreInitialise(uid_t uid, gid_t gid, int scfilter_level)
|
NKS_PreInitialise(uid_t uid, gid_t gid, int scfilter_level)
|
||||||
{
|
{
|
||||||
int i, processes, sock_fd1, sock_fd2;
|
int i, processes, sock_fd1, sock_fd2;
|
||||||
|
const char **certs, **keys;
|
||||||
char prefix[16];
|
char prefix[16];
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
helper_sock_fd = INVALID_SOCK_FD;
|
helper_sock_fd = INVALID_SOCK_FD;
|
||||||
is_helper = 0;
|
is_helper = 0;
|
||||||
|
|
||||||
if (!CNF_GetNtsServerCertFile() || !CNF_GetNtsServerKeyFile())
|
if (CNF_GetNtsServerCertAndKeyFiles(&certs, &keys) <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
processes = CNF_GetNtsServerProcesses();
|
processes = CNF_GetNtsServerProcesses();
|
||||||
|
@ -728,21 +729,19 @@ NKS_PreInitialise(uid_t uid, gid_t gid, int scfilter_level)
|
||||||
void
|
void
|
||||||
NKS_Initialise(void)
|
NKS_Initialise(void)
|
||||||
{
|
{
|
||||||
char *cert, *key;
|
const char **certs, **keys;
|
||||||
|
int i, n_certs_keys;
|
||||||
double key_delay;
|
double key_delay;
|
||||||
int i;
|
|
||||||
|
|
||||||
server_sock_fd4 = INVALID_SOCK_FD;
|
server_sock_fd4 = INVALID_SOCK_FD;
|
||||||
server_sock_fd6 = INVALID_SOCK_FD;
|
server_sock_fd6 = INVALID_SOCK_FD;
|
||||||
|
|
||||||
cert = CNF_GetNtsServerCertFile();
|
n_certs_keys = CNF_GetNtsServerCertAndKeyFiles(&certs, &keys);
|
||||||
key = CNF_GetNtsServerKeyFile();
|
if (n_certs_keys <= 0)
|
||||||
|
|
||||||
if (!cert || !key)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (helper_sock_fd == INVALID_SOCK_FD) {
|
if (helper_sock_fd == INVALID_SOCK_FD) {
|
||||||
server_credentials = NKSN_CreateServerCertCredentials(cert, key);
|
server_credentials = NKSN_CreateServerCertCredentials(certs, keys, n_certs_keys);
|
||||||
if (!server_credentials)
|
if (!server_credentials)
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -642,10 +642,11 @@ deinit_gnutls(void)
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
static NKSN_Credentials
|
static NKSN_Credentials
|
||||||
create_credentials(const char *cert, const char *key, const char *trusted_certs)
|
create_credentials(const char **certs, const char **keys, int n_certs_keys,
|
||||||
|
const char *trusted_certs)
|
||||||
{
|
{
|
||||||
gnutls_certificate_credentials_t credentials = NULL;
|
gnutls_certificate_credentials_t credentials = NULL;
|
||||||
int r;
|
int i, r;
|
||||||
|
|
||||||
init_gnutls();
|
init_gnutls();
|
||||||
|
|
||||||
|
@ -653,15 +654,18 @@ create_credentials(const char *cert, const char *key, const char *trusted_certs)
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (cert && key) {
|
if (certs && keys) {
|
||||||
assert(!trusted_certs);
|
assert(!trusted_certs);
|
||||||
|
|
||||||
r = gnutls_certificate_set_x509_key_file(credentials, cert, key,
|
for (i = 0; i < n_certs_keys; i++) {
|
||||||
|
r = gnutls_certificate_set_x509_key_file(credentials, certs[i], keys[i],
|
||||||
GNUTLS_X509_FMT_PEM);
|
GNUTLS_X509_FMT_PEM);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(!cert && !key);
|
if (certs || keys || n_certs_keys > 0)
|
||||||
|
assert(0);
|
||||||
|
|
||||||
if (!CNF_GetNoSystemCert()) {
|
if (!CNF_GetNoSystemCert()) {
|
||||||
r = gnutls_certificate_set_x509_system_trust(credentials);
|
r = gnutls_certificate_set_x509_system_trust(credentials);
|
||||||
|
@ -692,9 +696,9 @@ error:
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
NKSN_Credentials
|
NKSN_Credentials
|
||||||
NKSN_CreateServerCertCredentials(const char *cert, const char *key)
|
NKSN_CreateServerCertCredentials(const char **certs, const char **keys, int n_certs_keys)
|
||||||
{
|
{
|
||||||
return create_credentials(cert, key, NULL);
|
return create_credentials(certs, keys, n_certs_keys, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
@ -702,7 +706,7 @@ NKSN_CreateServerCertCredentials(const char *cert, const char *key)
|
||||||
NKSN_Credentials
|
NKSN_Credentials
|
||||||
NKSN_CreateClientCertCredentials(const char *trusted_certs)
|
NKSN_CreateClientCertCredentials(const char *trusted_certs)
|
||||||
{
|
{
|
||||||
return create_credentials(NULL, NULL, trusted_certs);
|
return create_credentials(NULL, NULL, 0, trusted_certs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
|
@ -41,7 +41,8 @@ typedef int (*NKSN_MessageHandler)(void *arg);
|
||||||
/* Get server or client credentials using a server certificate and key,
|
/* Get server or client credentials using a server certificate and key,
|
||||||
or certificates of trusted CAs. The credentials may be shared between
|
or certificates of trusted CAs. The credentials may be shared between
|
||||||
different clients or servers. */
|
different clients or servers. */
|
||||||
extern NKSN_Credentials NKSN_CreateServerCertCredentials(const char *cert, const char *key);
|
extern NKSN_Credentials NKSN_CreateServerCertCredentials(const char **certs, const char **keys,
|
||||||
|
int n_certs_keys);
|
||||||
extern NKSN_Credentials NKSN_CreateClientCertCredentials(const char *trusted_certs);
|
extern NKSN_Credentials NKSN_CreateClientCertCredentials(const char *trusted_certs);
|
||||||
|
|
||||||
/* Destroy the credentials */
|
/* Destroy the credentials */
|
||||||
|
|
|
@ -59,8 +59,10 @@ struct NtsServer *server;
|
||||||
void
|
void
|
||||||
NNS_Initialise(void)
|
NNS_Initialise(void)
|
||||||
{
|
{
|
||||||
|
const char **certs, **keys;
|
||||||
|
|
||||||
/* Create an NTS-NTP server instance only if NTS-KE server is enabled */
|
/* Create an NTS-NTP server instance only if NTS-KE server is enabled */
|
||||||
if (!CNF_GetNtsServerCertFile() || !CNF_GetNtsServerKeyFile()) {
|
if (CNF_GetNtsServerCertAndKeyFiles(&certs, &keys) <= 0) {
|
||||||
server = NULL;
|
server = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,19 +163,23 @@ void
|
||||||
test_unit(void)
|
test_unit(void)
|
||||||
{
|
{
|
||||||
NKSN_Credentials client_cred, server_cred;
|
NKSN_Credentials client_cred, server_cred;
|
||||||
|
const char *cert, *key;
|
||||||
int sock_fds[2], i;
|
int sock_fds[2], i;
|
||||||
|
|
||||||
LCL_Initialise();
|
LCL_Initialise();
|
||||||
TST_RegisterDummyDrivers();
|
TST_RegisterDummyDrivers();
|
||||||
|
|
||||||
|
cert = "nts_ke.crt";
|
||||||
|
key = "nts_ke.key";
|
||||||
|
|
||||||
for (i = 0; i < 50; i++) {
|
for (i = 0; i < 50; i++) {
|
||||||
SCH_Initialise();
|
SCH_Initialise();
|
||||||
|
|
||||||
server = NKSN_CreateInstance(1, NULL, handle_request, NULL);
|
server = NKSN_CreateInstance(1, NULL, handle_request, NULL);
|
||||||
client = NKSN_CreateInstance(0, "test", handle_response, NULL);
|
client = NKSN_CreateInstance(0, "test", handle_response, NULL);
|
||||||
|
|
||||||
server_cred = NKSN_CreateServerCertCredentials("nts_ke.crt", "nts_ke.key");
|
server_cred = NKSN_CreateServerCertCredentials(&cert, &key, 1);
|
||||||
client_cred = NKSN_CreateClientCertCredentials("nts_ke.crt");
|
client_cred = NKSN_CreateClientCertCredentials(cert);
|
||||||
|
|
||||||
TEST_CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fds) == 0);
|
TEST_CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fds) == 0);
|
||||||
TEST_CHECK(fcntl(sock_fds[0], F_SETFL, O_NONBLOCK) == 0);
|
TEST_CHECK(fcntl(sock_fds[0], F_SETFL, O_NONBLOCK) == 0);
|
||||||
|
|
Loading…
Reference in a new issue