nts: allow multiple files with trusted certificates

Allow the ntstrustedcerts directive to be specified multiple times.
This commit is contained in:
Miroslav Lichvar 2021-02-11 12:20:59 +01:00
parent 90557cf1ba
commit 316d47e3b4
7 changed files with 46 additions and 19 deletions

31
conf.c
View file

@ -77,6 +77,7 @@ 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_ntstrustedcerts(char *);
static void parse_ratelimit(char *line, int *enabled, int *interval,
int *burst, int *leak);
static void parse_refclock(char *);
@ -260,7 +261,7 @@ static int nts_server_processes = 1;
static int nts_server_connections = 100;
static int nts_refresh = 2419200; /* 4 weeks */
static int nts_rotate = 604800; /* 1 week */
static char *nts_trusted_cert_file = NULL;
static ARR_Instance nts_trusted_certs_files; /* array of (char *) */
/* Number of clock updates needed to enable certificate time checks */
static int no_cert_time_check = 0;
@ -391,6 +392,7 @@ CNF_Initialise(int r, int client_only)
nts_server_cert_files = ARR_CreateInstance(sizeof (char *));
nts_server_key_files = ARR_CreateInstance(sizeof (char *));
nts_trusted_certs_files = ARR_CreateInstance(sizeof (char *));
rtc_device = Strdup(DEFAULT_RTC_DEVICE);
hwclock_file = Strdup(DEFAULT_HWCLOCK_FILE);
@ -434,6 +436,8 @@ CNF_Finalise(void)
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));
for (i = 0; i < ARR_GetSize(nts_trusted_certs_files); i++)
Free(*(char **)ARR_GetElement(nts_trusted_certs_files, i));
ARR_DestroyInstance(init_sources);
ARR_DestroyInstance(ntp_sources);
@ -447,6 +451,7 @@ CNF_Finalise(void)
ARR_DestroyInstance(nts_server_cert_files);
ARR_DestroyInstance(nts_server_key_files);
ARR_DestroyInstance(nts_trusted_certs_files);
Free(drift_file);
Free(dumpdir);
@ -468,7 +473,6 @@ CNF_Finalise(void)
Free(tempcomp_point_file);
Free(nts_dump_dir);
Free(nts_ntp_server);
Free(nts_trusted_cert_file);
}
/* ================================================== */
@ -652,8 +656,6 @@ CNF_ParseLine(const char *filename, int number, char *line)
} else if (!strcasecmp(command, "ntsratelimit")) {
parse_ratelimit(p, &nts_ratelimit_enabled, &nts_ratelimit_interval,
&nts_ratelimit_burst, &nts_ratelimit_leak);
} else if (!strcasecmp(command, "ntstrustedcerts")) {
parse_string(p, &nts_trusted_cert_file);
} else if (!strcasecmp(command, "ntscachedir") ||
!strcasecmp(command, "ntsdumpdir")) {
parse_string(p, &nts_dump_dir);
@ -671,6 +673,8 @@ CNF_ParseLine(const char *filename, int number, char *line)
parse_ntsserver(p, nts_server_cert_files);
} else if (!strcasecmp(command, "ntsserverkey")) {
parse_ntsserver(p, nts_server_key_files);
} else if (!strcasecmp(command, "ntstrustedcerts")) {
parse_ntstrustedcerts(p);
} else if (!strcasecmp(command, "peer")) {
parse_source(p, command, 1);
} else if (!strcasecmp(command, "pidfile")) {
@ -1178,6 +1182,17 @@ parse_ntsserver(char *line, ARR_Instance files)
/* ================================================== */
static void
parse_ntstrustedcerts(char *line)
{
char *file = NULL;
parse_string(line, &file);
ARR_AppendElement(nts_trusted_certs_files, &file);
}
/* ================================================== */
static void
parse_allow_deny(char *line, ARR_Instance restrictions, int allow)
{
@ -2589,10 +2604,12 @@ CNF_GetNtsRotate(void)
/* ================================================== */
char *
CNF_GetNtsTrustedCertFile(void)
int
CNF_GetNtsTrustedCertsFiles(const char ***files)
{
return nts_trusted_cert_file;
*files = ARR_GetElements(nts_trusted_certs_files);
return ARR_GetSize(nts_trusted_certs_files);
}
/* ================================================== */

2
conf.h
View file

@ -159,7 +159,7 @@ extern int CNF_GetNtsServerProcesses(void);
extern int CNF_GetNtsServerConnections(void);
extern int CNF_GetNtsRefresh(void);
extern int CNF_GetNtsRotate(void);
extern char *CNF_GetNtsTrustedCertFile(void);
extern int CNF_GetNtsTrustedCertsFiles(const char ***files);
extern int CNF_GetNoSystemCert(void);
extern int CNF_GetNoCertTimeCheck(void);

View file

@ -755,6 +755,9 @@ This directive specifies a file containing certificates (in the PEM format) of
trusted certificate authorities (CA) that should be used to verify certificates
of NTS servers in addition to the system's default trusted CAs (if the
*nosystemcert* directive is not present).
+
This directive can be used multiple times to specify multiple files with
trusted certificates.
[[nosystemcert]]*nosystemcert*::
This directive disables the system's default trusted CAs.

View file

@ -268,7 +268,9 @@ handle_message(void *arg)
NKC_Instance
NKC_CreateInstance(IPSockAddr *address, const char *name)
{
const char **trusted_certs;
NKC_Instance inst;
int n_certs;
inst = MallocNew(struct NKC_Instance_Record);
@ -279,9 +281,11 @@ NKC_CreateInstance(IPSockAddr *address, const char *name)
inst->destroying = 0;
inst->got_response = 0;
n_certs = CNF_GetNtsTrustedCertsFiles(&trusted_certs);
/* Share the credentials with other client instances */
if (!client_credentials)
client_credentials = NKSN_CreateClientCertCredentials(CNF_GetNtsTrustedCertFile());
client_credentials = NKSN_CreateClientCertCredentials(trusted_certs, n_certs);
client_credentials_refs++;
return inst;

View file

@ -643,7 +643,7 @@ deinit_gnutls(void)
static NKSN_Credentials
create_credentials(const char **certs, const char **keys, int n_certs_keys,
const char *trusted_certs)
const char **trusted_certs, int n_trusted_certs)
{
gnutls_certificate_credentials_t credentials = NULL;
int i, r;
@ -674,10 +674,12 @@ create_credentials(const char **certs, const char **keys, int n_certs_keys,
}
if (trusted_certs) {
r = gnutls_certificate_set_x509_trust_file(credentials, trusted_certs,
GNUTLS_X509_FMT_PEM);
if (r < 0)
goto error;
for (i = 0; i < n_trusted_certs; i++) {
r = gnutls_certificate_set_x509_trust_file(credentials, trusted_certs[i],
GNUTLS_X509_FMT_PEM);
if (r < 0)
goto error;
}
}
}
@ -698,15 +700,15 @@ error:
NKSN_Credentials
NKSN_CreateServerCertCredentials(const char **certs, const char **keys, int n_certs_keys)
{
return create_credentials(certs, keys, n_certs_keys, NULL);
return create_credentials(certs, keys, n_certs_keys, NULL, 0);
}
/* ================================================== */
NKSN_Credentials
NKSN_CreateClientCertCredentials(const char *trusted_certs)
NKSN_CreateClientCertCredentials(const char **trusted_certs, int n_certs)
{
return create_credentials(NULL, NULL, 0, trusted_certs);
return create_credentials(NULL, NULL, 0, trusted_certs, n_certs);
}
/* ================================================== */

View file

@ -43,7 +43,8 @@ typedef int (*NKSN_MessageHandler)(void *arg);
different clients or servers. */
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,
int n_certs);
/* Destroy the credentials */
extern void NKSN_DestroyCertCredentials(NKSN_Credentials credentials);

View file

@ -179,7 +179,7 @@ test_unit(void)
client = NKSN_CreateInstance(0, "test", handle_response, NULL);
server_cred = NKSN_CreateServerCertCredentials(&cert, &key, 1);
client_cred = NKSN_CreateClientCertCredentials(cert);
client_cred = NKSN_CreateClientCertCredentials(&cert, 1);
TEST_CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fds) == 0);
TEST_CHECK(fcntl(sock_fds[0], F_SETFL, O_NONBLOCK) == 0);