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_makestep(char *);
|
||||
static void parse_maxchange(char *);
|
||||
static void parse_ntsserver(char *, ARR_Instance files);
|
||||
static void parse_ratelimit(char *line, int *enabled, int *interval,
|
||||
int *burst, int *leak);
|
||||
static void parse_refclock(char *);
|
||||
|
@ -252,8 +253,8 @@ static char *user;
|
|||
/* NTS server and client configuration */
|
||||
static char *nts_dump_dir = NULL;
|
||||
static char *nts_ntp_server = NULL;
|
||||
static char *nts_server_cert_file = NULL;
|
||||
static char *nts_server_key_file = NULL;
|
||||
static ARR_Instance nts_server_cert_files; /* array of (char *) */
|
||||
static ARR_Instance nts_server_key_files; /* array of (char *) */
|
||||
static int nts_server_port = NKE_PORT;
|
||||
static int nts_server_processes = 1;
|
||||
static int nts_server_connections = 100;
|
||||
|
@ -388,6 +389,9 @@ CNF_Initialise(int r, int client_only)
|
|||
ntp_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);
|
||||
hwclock_file = Strdup(DEFAULT_HWCLOCK_FILE);
|
||||
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_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(ntp_sources);
|
||||
|
@ -437,6 +445,9 @@ CNF_Finalise(void)
|
|||
ARR_DestroyInstance(ntp_restrictions);
|
||||
ARR_DestroyInstance(cmd_restrictions);
|
||||
|
||||
ARR_DestroyInstance(nts_server_cert_files);
|
||||
ARR_DestroyInstance(nts_server_key_files);
|
||||
|
||||
Free(drift_file);
|
||||
Free(dumpdir);
|
||||
Free(hwclock_file);
|
||||
|
@ -457,8 +468,6 @@ CNF_Finalise(void)
|
|||
Free(tempcomp_point_file);
|
||||
Free(nts_dump_dir);
|
||||
Free(nts_ntp_server);
|
||||
Free(nts_server_cert_file);
|
||||
Free(nts_server_key_file);
|
||||
Free(nts_trusted_cert_file);
|
||||
}
|
||||
|
||||
|
@ -659,9 +668,9 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
|||
} else if (!strcasecmp(command, "ntsrotate")) {
|
||||
parse_int(p, &nts_rotate);
|
||||
} else if (!strcasecmp(command, "ntsservercert")) {
|
||||
parse_string(p, &nts_server_cert_file);
|
||||
parse_ntsserver(p, nts_server_cert_files);
|
||||
} else if (!strcasecmp(command, "ntsserverkey")) {
|
||||
parse_string(p, &nts_server_key_file);
|
||||
parse_ntsserver(p, nts_server_key_files);
|
||||
} else if (!strcasecmp(command, "peer")) {
|
||||
parse_source(p, command, 1);
|
||||
} 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
|
||||
parse_allow_deny(char *line, ARR_Instance restrictions, int allow)
|
||||
{
|
||||
|
@ -2515,18 +2535,16 @@ CNF_GetNtsNtpServer(void)
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
char *
|
||||
CNF_GetNtsServerCertFile(void)
|
||||
int
|
||||
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 *
|
||||
CNF_GetNtsServerKeyFile(void)
|
||||
{
|
||||
return nts_server_key_file;
|
||||
return ARR_GetSize(nts_server_cert_files);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
|
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_GetNtsNtpServer(void);
|
||||
extern char *CNF_GetNtsServerCertFile(void);
|
||||
extern char *CNF_GetNtsServerKeyFile(void);
|
||||
extern int CNF_GetNtsServerCertAndKeyFiles(const char ***certs, const char ***keys);
|
||||
extern int CNF_GetNtsServerPort(void);
|
||||
extern int CNF_GetNtsServerProcesses(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_::
|
||||
This directive specifies a file containing a certificate in the PEM format
|
||||
for *chronyd* to operate as an NTS server.
|
||||
+
|
||||
This directive can be used multiple times to specify multiple certificates.
|
||||
|
||||
[[ntsserverkey]]*ntsserverkey* _file_::
|
||||
This directive specifies a file containing a private key in the PEM format
|
||||
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_::
|
||||
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)
|
||||
{
|
||||
int i, processes, sock_fd1, sock_fd2;
|
||||
const char **certs, **keys;
|
||||
char prefix[16];
|
||||
pid_t pid;
|
||||
|
||||
helper_sock_fd = INVALID_SOCK_FD;
|
||||
is_helper = 0;
|
||||
|
||||
if (!CNF_GetNtsServerCertFile() || !CNF_GetNtsServerKeyFile())
|
||||
if (CNF_GetNtsServerCertAndKeyFiles(&certs, &keys) <= 0)
|
||||
return;
|
||||
|
||||
processes = CNF_GetNtsServerProcesses();
|
||||
|
@ -728,21 +729,19 @@ NKS_PreInitialise(uid_t uid, gid_t gid, int scfilter_level)
|
|||
void
|
||||
NKS_Initialise(void)
|
||||
{
|
||||
char *cert, *key;
|
||||
const char **certs, **keys;
|
||||
int i, n_certs_keys;
|
||||
double key_delay;
|
||||
int i;
|
||||
|
||||
server_sock_fd4 = INVALID_SOCK_FD;
|
||||
server_sock_fd6 = INVALID_SOCK_FD;
|
||||
|
||||
cert = CNF_GetNtsServerCertFile();
|
||||
key = CNF_GetNtsServerKeyFile();
|
||||
|
||||
if (!cert || !key)
|
||||
n_certs_keys = CNF_GetNtsServerCertAndKeyFiles(&certs, &keys);
|
||||
if (n_certs_keys <= 0)
|
||||
return;
|
||||
|
||||
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)
|
||||
return;
|
||||
} else {
|
||||
|
|
|
@ -642,10 +642,11 @@ deinit_gnutls(void)
|
|||
/* ================================================== */
|
||||
|
||||
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;
|
||||
int r;
|
||||
int i, r;
|
||||
|
||||
init_gnutls();
|
||||
|
||||
|
@ -653,15 +654,18 @@ create_credentials(const char *cert, const char *key, const char *trusted_certs)
|
|||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
if (cert && key) {
|
||||
if (certs && keys) {
|
||||
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);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
assert(!cert && !key);
|
||||
if (certs || keys || n_certs_keys > 0)
|
||||
assert(0);
|
||||
|
||||
if (!CNF_GetNoSystemCert()) {
|
||||
r = gnutls_certificate_set_x509_system_trust(credentials);
|
||||
|
@ -692,9 +696,9 @@ error:
|
|||
/* ================================================== */
|
||||
|
||||
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_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,
|
||||
or certificates of trusted CAs. The credentials may be shared between
|
||||
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);
|
||||
|
||||
/* Destroy the credentials */
|
||||
|
|
|
@ -59,8 +59,10 @@ struct NtsServer *server;
|
|||
void
|
||||
NNS_Initialise(void)
|
||||
{
|
||||
const char **certs, **keys;
|
||||
|
||||
/* 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;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -163,19 +163,23 @@ void
|
|||
test_unit(void)
|
||||
{
|
||||
NKSN_Credentials client_cred, server_cred;
|
||||
const char *cert, *key;
|
||||
int sock_fds[2], i;
|
||||
|
||||
LCL_Initialise();
|
||||
TST_RegisterDummyDrivers();
|
||||
|
||||
cert = "nts_ke.crt";
|
||||
key = "nts_ke.key";
|
||||
|
||||
for (i = 0; i < 50; i++) {
|
||||
SCH_Initialise();
|
||||
|
||||
server = NKSN_CreateInstance(1, NULL, handle_request, NULL);
|
||||
client = NKSN_CreateInstance(0, "test", handle_response, NULL);
|
||||
|
||||
server_cred = NKSN_CreateServerCertCredentials("nts_ke.crt", "nts_ke.key");
|
||||
client_cred = NKSN_CreateClientCertCredentials("nts_ke.crt");
|
||||
server_cred = NKSN_CreateServerCertCredentials(&cert, &key, 1);
|
||||
client_cred = NKSN_CreateClientCertCredentials(cert);
|
||||
|
||||
TEST_CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fds) == 0);
|
||||
TEST_CHECK(fcntl(sock_fds[0], F_SETFL, O_NONBLOCK) == 0);
|
||||
|
|
Loading…
Reference in a new issue