From 316d47e3b40c28c9d6e38fe18900b7828f497649 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Thu, 11 Feb 2021 12:20:59 +0100 Subject: [PATCH] nts: allow multiple files with trusted certificates Allow the ntstrustedcerts directive to be specified multiple times. --- conf.c | 31 ++++++++++++++++++++++++------- conf.h | 2 +- doc/chrony.conf.adoc | 3 +++ nts_ke_client.c | 6 +++++- nts_ke_session.c | 18 ++++++++++-------- nts_ke_session.h | 3 ++- test/unit/nts_ke_session.c | 2 +- 7 files changed, 46 insertions(+), 19 deletions(-) diff --git a/conf.c b/conf.c index 4c62a07..3ae0254 100644 --- a/conf.c +++ b/conf.c @@ -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); } /* ================================================== */ diff --git a/conf.h b/conf.h index cf5fc3b..025ca60 100644 --- a/conf.h +++ b/conf.h @@ -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); diff --git a/doc/chrony.conf.adoc b/doc/chrony.conf.adoc index d9da7b4..a1de814 100644 --- a/doc/chrony.conf.adoc +++ b/doc/chrony.conf.adoc @@ -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. diff --git a/nts_ke_client.c b/nts_ke_client.c index 5e87fe4..59a9730 100644 --- a/nts_ke_client.c +++ b/nts_ke_client.c @@ -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; diff --git a/nts_ke_session.c b/nts_ke_session.c index d92b4c2..131ad90 100644 --- a/nts_ke_session.c +++ b/nts_ke_session.c @@ -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); } /* ================================================== */ diff --git a/nts_ke_session.h b/nts_ke_session.h index ed9c711..eb19b92 100644 --- a/nts_ke_session.h +++ b/nts_ke_session.h @@ -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); diff --git a/test/unit/nts_ke_session.c b/test/unit/nts_ke_session.c index b29675b..1dd9aba 100644 --- a/test/unit/nts_ke_session.c +++ b/test/unit/nts_ke_session.c @@ -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);