static void parse_maxchange(char *);
static void parse_ntsserver(char *, ARR_Instance files);
static void parse_ntstrustedcerts(char *);
+static void parse_open_commands(char *line);
static void parse_pidfile(char *line);
static void parse_ratelimit(char *line, int *enabled, int *interval,
int *burst, int *leak, int *kod);
static ARR_Instance ntp_restrictions;
static ARR_Instance cmd_restrictions;
+#define DEFAULT_OPEN_COMMANDS "activity manual rtcdata smoothing sourcename sources sourcestats tracking"
+
+/* Array of int specifying commands allowed from network */
+static ARR_Instance open_commands;
+
typedef struct {
NTP_Remote_Address addr;
int interval;
void
CNF_Initialise(int r, int client_only)
{
- char buf[10];
+ char buf[128];
restarted = r;
ntp_restrictions = ARR_CreateInstance(sizeof (AllowDeny));
cmd_restrictions = ARR_CreateInstance(sizeof (AllowDeny));
+ open_commands = ARR_CreateInstance(sizeof (int));
+ snprintf(buf, sizeof (buf), DEFAULT_OPEN_COMMANDS);
+ parse_open_commands(buf);
+
nts_aeads = ARR_CreateInstance(sizeof (int));
snprintf(buf, sizeof (buf), DEFAULT_NTS_AEADS);
parse_ints(buf, nts_aeads);
ARR_DestroyInstance(refclock_sources);
ARR_DestroyInstance(broadcasts);
+ ARR_DestroyInstance(open_commands);
+
ARR_DestroyInstance(ntp_restrictions);
ARR_DestroyInstance(cmd_restrictions);
parse_ntsserver(p, nts_server_key_files);
} else if (!strcasecmp(command, "ntstrustedcerts")) {
parse_ntstrustedcerts(p);
+ } else if (!strcasecmp(command, "opencommands")) {
+ parse_open_commands(p);
} else if (!strcasecmp(command, "peer")) {
parse_source(p, command, 1);
} else if (!strcasecmp(command, "pidfile")) {
/* ================================================== */
+static void
+add_open_command(int command)
+{
+ int i;
+
+ /* Avoid duplicates */
+ for (i = 0; i < ARR_GetSize(open_commands); i++) {
+ if (*(int *)ARR_GetElement(open_commands, i) == command)
+ return;
+ }
+
+ ARR_AppendElement(open_commands, &command);
+}
+
+/* ================================================== */
+
+static void
+parse_open_commands(char *line)
+{
+ char *s;
+
+ ARR_SetSize(open_commands, 0);
+
+ while (*line) {
+ s = line;
+ line = CPS_SplitWord(line);
+
+ if (strcasecmp(s, "activity") == 0) {
+ add_open_command(REQ_ACTIVITY);
+ } else if (strcasecmp(s, "authdata") == 0) {
+ add_open_command(REQ_N_SOURCES);
+ add_open_command(REQ_AUTH_DATA);
+ } else if (strcasecmp(s, "clients") == 0) {
+ add_open_command(REQ_CLIENT_ACCESSES_BY_INDEX3);
+ } else if (strcasecmp(s, "manual") == 0) {
+ add_open_command(REQ_MANUAL_LIST);
+ } else if (strcasecmp(s, "ntpdata") == 0) {
+ add_open_command(REQ_N_SOURCES);
+ add_open_command(REQ_NTP_DATA);
+ } else if (strcasecmp(s, "rtcdata") == 0) {
+ add_open_command(REQ_RTCREPORT);
+ } else if (strcasecmp(s, "selectdata") == 0) {
+ add_open_command(REQ_N_SOURCES);
+ add_open_command(REQ_SELECT_DATA);
+ } else if (strcasecmp(s, "serverstats") == 0) {
+ add_open_command(REQ_SERVER_STATS);
+ } else if (strcasecmp(s, "smoothing") == 0) {
+ add_open_command(REQ_SMOOTHING);
+ } else if (strcasecmp(s, "sourcename") == 0) {
+ add_open_command(REQ_NTP_SOURCE_NAME);
+ } else if (strcasecmp(s, "sources") == 0) {
+ add_open_command(REQ_N_SOURCES);
+ add_open_command(REQ_SOURCE_DATA);
+ } else if (strcasecmp(s, "sourcestats") == 0) {
+ add_open_command(REQ_N_SOURCES);
+ add_open_command(REQ_SOURCESTATS);
+ } else if (strcasecmp(s, "tracking") == 0) {
+ add_open_command(REQ_TRACKING);
+ } else {
+ command_parse_error();
+ }
+ }
+}
+
+/* ================================================== */
+
static void
parse_allow_deny(char *line, ARR_Instance restrictions, int allow)
{
/* ================================================== */
+ARR_Instance
+CNF_GetOpenCommands(void)
+{
+ return open_commands;
+}
+
+/* ================================================== */
+
int
CNF_GetCommandPort(void) {
return cmd_port;
cmdratelimit interval 2
----
+[[opencommands]]*opencommands* [_command_]...::
+This directive specifies a list of monitoring commands to be enabled for the
+hosts allowed by the *cmdallow* directive. The following commands can be
+specified (the naming follows *chronyc*):
++
+*activity*+*+, *authdata*, *clients*, *manual*+*+, *ntpdata*, *rtcdata*+*+,
+*selectdata*, *serverstats*+*+, *smoothing*+*+, *sourcename*+*+, *sources*+*+,
+*sourcestats*, *tracking*+*+.
++
+The commands marked with +*+ are enabled by default. The protocol of these
+commands is considered stable and can be expected to work between different
+versions of *chronyc* and *chronyd*. The protocol of the other commands is not
+considered stable and different versions of *chronyc* and *chronyd* may not
+interoperate. When that happens, *chronyc* will print an '`Invalid command`' or
+'`Bad reply from daemon`' error.
++
+Note that some of the reported data can be potentially useful to attackers,
+enabling them to better observe and predict the internal state of *chronyd*.
+It is recommended to enable only commands that are actually needed for
+monitoring and limit the access to the hosts that need it.
+
=== Real-time clock (RTC)
[[hwclockfile]]*hwclockfile* _file_::
::1.
Only the following monitoring commands, which do not affect the behaviour of
-*chronyd*, are allowed from the network: *activity*, *manual list*,
+*chronyd*, are allowed from the network by default: *activity*, *manual list*,
*rtcdata*, *smoothing*, *sourcename*, *sources*, *sourcestats*, *tracking*,
*waitsync*. The
set of hosts from which *chronyd* will accept these commands can be configured
configuration file or the <<cmdallow,*cmdallow*>> command in *chronyc*. By
default, the commands are accepted only from localhost (127.0.0.1 or ::1).
-All other commands are allowed only through the Unix domain socket. When sent
+Other monitoring commands can be enabled for network access by the
+<<chrony.conf.adoc#opencommands,*opencommands*>> directive. Monitoring commands
+with disabled network access and commands that affect the behaviour of
+*chronyd* are allowed only through the Unix domain socket. If they are sent
over the network, *chronyd* will respond with a '`Not authorised`' error, even
if it is from localhost.