From 52e12e42e523cde5a7259c8e9fe7ec719d832d7e Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Tue, 6 Jan 2015 15:12:26 +0100 Subject: [PATCH] ntp: open server socket only when access is allowed When changing access configuration, check if any address is allowed and open/close the server socket as needed. --- addrfilt.c | 38 ++++++++++++++++++++++++++++++++++++++ addrfilt.h | 5 +++++ chrony.texi.in | 6 ++++-- ntp_core.c | 41 +++++++++++++++++++++++++++++++---------- 4 files changed, 78 insertions(+), 12 deletions(-) diff --git a/addrfilt.c b/addrfilt.c index 0930289..98d66a8 100644 --- a/addrfilt.c +++ b/addrfilt.c @@ -363,6 +363,44 @@ ADF_IsAllowed(ADF_AuthTable table, /* ================================================== */ +static int +is_any_allowed(TableNode *node, State parent) +{ + State state; + int i; + + state = node->state != AS_PARENT ? node->state : parent; + assert(state != AS_PARENT); + + if (node->extended) { + for (i = 0; i < TABLE_SIZE; i++) { + if (is_any_allowed(&node->extended[i], state)) + return 1; + } + } else if (state == ALLOW) { + return 1; + } + + return 0; +} + +/* ================================================== */ + +int +ADF_IsAnyAllowed(ADF_AuthTable table, int family) +{ + switch (family) { + case IPADDR_INET4: + return is_any_allowed(&table->base4, AS_PARENT); + case IPADDR_INET6: + return is_any_allowed(&table->base6, AS_PARENT); + default: + return 0; + } +} + +/* ================================================== */ + #if defined TEST static void print_node(TableNode *node, uint32_t *addr, int ip_len, int shift, int subnet_bits) diff --git a/addrfilt.h b/addrfilt.h index 65784e5..b8c131f 100644 --- a/addrfilt.h +++ b/addrfilt.h @@ -72,4 +72,9 @@ extern void ADF_DestroyTable(ADF_AuthTable table); extern int ADF_IsAllowed(ADF_AuthTable table, IPAddr *ip); +/* Check if at least one address from a given family is allowed by + the rules in the table */ +extern int ADF_IsAnyAllowed(ADF_AuthTable table, + int family); + #endif /* GOT_ADDRFILT_H */ diff --git a/chrony.texi.in b/chrony.texi.in index 277b924..c82758e 100644 --- a/chrony.texi.in +++ b/chrony.texi.in @@ -2523,10 +2523,12 @@ pool pool.ntp.org iburst maxsources 3 @node port directive @subsection port This option allows you to configure the port on which @code{chronyd} -will listen for NTP requests. +will listen for NTP requests. The port will be open only when an address is +allowed by the @code{allow} directive or command, an NTP peer is configured, or +the broadcast server mode is enabled. The compiled in default is udp/123, the standard NTP port. If set to 0, -@code{chronyd} will not open the server socket and will operate strictly in a +@code{chronyd} will never open the server port and will operate strictly in a client-only mode. The source port used in NTP client requests can be set by the @code{acquisitionport} directive. diff --git a/ntp_core.c b/ntp_core.c index e936a09..8615bc8 100644 --- a/ntp_core.c +++ b/ntp_core.c @@ -309,8 +309,6 @@ do_time_checks(void) void NCR_Initialise(void) { - NTP_Remote_Address addr; - do_size_checks(); do_time_checks(); @@ -321,10 +319,9 @@ NCR_Initialise(void) access_auth_table = ADF_CreateTable(); broadcasts = ARR_CreateInstance(sizeof (BroadcastDestination)); - addr.ip_addr.family = IPADDR_INET4; - server_sock_fd4 = NIO_OpenServerSocket(&addr); - addr.ip_addr.family = IPADDR_INET6; - server_sock_fd6 = NIO_OpenServerSocket(&addr); + /* Server socket will be opened when access is allowed */ + server_sock_fd4 = INVALID_SOCK_FD; + server_sock_fd6 = INVALID_SOCK_FD; } /* ================================================== */ @@ -1855,13 +1852,37 @@ NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all) } } - if (status == ADF_BADSUBNET) { + if (status != ADF_SUCCESS) return 0; - } else if (status == ADF_SUCCESS) { - return 1; + + /* Keep server sockets open only when an address allowed */ + if (allow) { + NTP_Remote_Address remote_addr; + + if (server_sock_fd4 == INVALID_SOCK_FD && + ADF_IsAnyAllowed(access_auth_table, IPADDR_INET4)) { + remote_addr.ip_addr.family = IPADDR_INET4; + server_sock_fd4 = NIO_OpenServerSocket(&remote_addr); + } + if (server_sock_fd6 == INVALID_SOCK_FD && + ADF_IsAnyAllowed(access_auth_table, IPADDR_INET6)) { + remote_addr.ip_addr.family = IPADDR_INET6; + server_sock_fd6 = NIO_OpenServerSocket(&remote_addr); + } } else { - return 0; + if (server_sock_fd4 != INVALID_SOCK_FD && + !ADF_IsAnyAllowed(access_auth_table, IPADDR_INET4)) { + NIO_CloseServerSocket(server_sock_fd4); + server_sock_fd4 = INVALID_SOCK_FD; + } + if (server_sock_fd6 != INVALID_SOCK_FD && + !ADF_IsAnyAllowed(access_auth_table, IPADDR_INET6)) { + NIO_CloseServerSocket(server_sock_fd6); + server_sock_fd6 = INVALID_SOCK_FD; + } } + + return 1; } /* ================================================== */