Skip to content

Commit

Permalink
Merge pull request #2738 from mlichvar/nts
Browse files Browse the repository at this point in the history
Add NTS support
  • Loading branch information
poncovka authored Jul 23, 2020
2 parents c9bdd68 + c236e3f commit 5444be2
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 15 deletions.
45 changes: 35 additions & 10 deletions pyanaconda/ntp.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@

#example line:
#server 0.fedora.pool.ntp.org iburst
SRV_LINE_REGEXP = re.compile(r"^\s*(server|pool)\s*([-a-zA-Z.0-9]+)\s*[a-zA-Z]+\s*$")
SRV_LINE_REGEXP = re.compile(r"^\s*(server|pool)\s*([-a-zA-Z.0-9]+)\s?([a-zA-Z0-9\s]*)$")
SRV_NOARG_OPTIONS = ["burst", "iburst", "nts", "prefer", "require", "trust", "noselect", "xleave"]
SRV_ARG_OPTIONS = ["key", "minpoll", "maxpoll"]

#treat pools as four servers with the same name
SERVERS_PER_POOL = 4
Expand Down Expand Up @@ -95,18 +97,24 @@ def get_ntp_servers_summary(servers, states):
return summary


def ntp_server_working(server_hostname):
def ntp_server_working(server_hostname, nts_enabled):
"""Tries to do an NTP request to the server (timeout may take some time).
If NTS is enabled, try making a TCP connection to the NTS-KE port instead.
:param server_hostname: a host name or an IP address of an NTP server
:type server_hostname: string
:return: True if the given server is reachable and working, False otherwise
:rtype: bool
"""
client = ntplib.NTPClient()

try:
client.request(server_hostname)
# ntplib doesn't support NTS
if nts_enabled:
s = socket.create_connection((server_hostname, 4460), 2)
s.close()
else:
client = ntplib.NTPClient()
client.request(server_hostname)
except ntplib.NTPException:
return False
# address related error
Expand Down Expand Up @@ -143,7 +151,23 @@ def get_servers_from_config(conf_file_path=NTP_CONFIG_FILE):
server = TimeSourceData()
server.type = match.group(1).upper()
server.hostname = match.group(2)
server.options = ["iburst"]
server.options = []

words = match.group(3).lower().split()
skip_argument = False

for i in range(len(words)):
if skip_argument:
skip_argument = False
continue
if words[i] in SRV_NOARG_OPTIONS:
server.options.append(words[i])
elif words[i] in SRV_ARG_OPTIONS and i + 1 < len(words):
server.options.append(' '.join(words[i:i+2]))
skip_argument = True
else:
log.debug("Unknown NTP server option %s", words[i])

servers.append(server)

except IOError as ioerr:
Expand Down Expand Up @@ -306,8 +330,9 @@ def check_status(self, server):
:param TimeSourceData server: an NTP server
"""
# Get a hostname.
# Get a hostname and NTS option.
hostname = server.hostname
nts_enabled = "nts" in server.options

# Reset the current status.
self._set_status(hostname, NTP_SERVER_QUERY)
Expand All @@ -316,7 +341,7 @@ def check_status(self, server):
threadMgr.add(AnacondaThread(
prefix=THREAD_NTP_SERVER_CHECK,
target=self._check_status,
args=(hostname, ))
args=(hostname, nts_enabled))
)

def _set_status(self, hostname, status):
Expand All @@ -327,13 +352,13 @@ def _set_status(self, hostname, status):
"""
self._cache[hostname] = status

def _check_status(self, hostname):
def _check_status(self, hostname, nts_enabled):
"""Check if an NTP server appears to be working.
:param str hostname: a hostname of an NTP server
"""
log.debug("Checking NTP server %s", hostname)
result = ntp_server_working(hostname)
result = ntp_server_working(hostname, nts_enabled)

if result:
log.debug("NTP server %s appears to be working.", hostname)
Expand Down
34 changes: 32 additions & 2 deletions pyanaconda/ui/gui/spokes/datetime_spoke.glade
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@
<column type="gchararray"/>
<!-- column-name pool -->
<column type="gboolean"/>
<!-- column-name nts -->
<column type="gboolean"/>
<!-- column-name working -->
<column type="gint"/>
<!-- column-name use -->
Expand Down Expand Up @@ -220,6 +222,21 @@
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="ntsCheckButton">
<property name="label" translatable="yes">Server supports Network Time Security (NTS) authentication</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledWindow">
<property name="visible">True</property>
Expand Down Expand Up @@ -266,6 +283,19 @@
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="nts">
<property name="title">NTS</property>
<child>
<object class="GtkCellRendererToggle" id="ntsRenderer">
<signal name="toggled" handler="on_nts_toggled" swapped="no"/>
</object>
<attributes>
<attribute name="active">2</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="workingColumn">
<property name="title" translatable="yes">Working</property>
Expand All @@ -282,7 +312,7 @@
<signal name="toggled" handler="on_use_server_toggled" swapped="no"/>
</object>
<attributes>
<attribute name="active">3</attribute>
<attribute name="active">4</attribute>
</attributes>
</child>
</object>
Expand All @@ -293,7 +323,7 @@
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">4</property>
<property name="position">5</property>
</packing>
</child>
</object>
Expand Down
26 changes: 23 additions & 3 deletions pyanaconda/ui/gui/spokes/datetime_spoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,10 @@

SERVER_HOSTNAME = 0
SERVER_POOL = 1
SERVER_WORKING = 2
SERVER_USE = 3
SERVER_OBJECT = 4
SERVER_NTS = 2
SERVER_WORKING = 3
SERVER_USE = 4
SERVER_OBJECT = 5

DEFAULT_TZ = "America/New_York"

Expand Down Expand Up @@ -184,6 +185,7 @@ def __init__(self, data, servers, states):
self._serversStore = self.builder.get_object("serversStore")
self._addButton = self.builder.get_object("addButton")
self._poolCheckButton = self.builder.get_object("poolCheckButton")
self._ntsCheckButton = self.builder.get_object("ntsCheckButton")

self._serverCheck = self.add_check(self._serverEntry, self._validate_server)
self._serverCheck.update_check_status()
Expand Down Expand Up @@ -256,6 +258,7 @@ def _add_row(self, server):
itr = self._serversStore.append([
"",
False,
False,
constants.NTP_SERVER_QUERY,
True,
server
Expand All @@ -268,6 +271,7 @@ def _refresh_row(self, itr):
server = self._serversStore[itr][SERVER_OBJECT]
self._serversStore.set_value(itr, SERVER_HOSTNAME, server.hostname)
self._serversStore.set_value(itr, SERVER_POOL, server.type == TIME_SOURCE_POOL)
self._serversStore.set_value(itr, SERVER_NTS, "nts" in server.options)

def _update_rows(self):
"""Periodically update the status of all rows.
Expand Down Expand Up @@ -300,12 +304,16 @@ def on_entry_activated(self, entry, *args):
server.hostname = entry.get_text()
server.options = ["iburst"]

if self._ntsCheckButton.get_active():
server.options.append("nts")

self._servers.append(server)
self._states.check_status(server)
self._add_row(server)

entry.set_text("")
self._poolCheckButton.set_active(False)
self._ntsCheckButton.set_active(False)

def on_add_clicked(self, *args):
self._serverEntry.emit("activate")
Expand All @@ -326,6 +334,18 @@ def on_pool_toggled(self, renderer, path, *args):

self._refresh_row(itr)

def on_nts_toggled(self, renderer, path, *args):
itr = self._serversStore.get_iter(path)
server = self._serversStore[itr][SERVER_OBJECT]

if "nts" in server.options:
server.options.remove("nts")
else:
server.options.append("nts")

self._states.check_status(server)
self._refresh_row(itr)

def on_server_editing_started(self, renderer, editable, path):
itr = self._serversStore.get_iter(path)
self._active_server = self._serversStore[itr][SERVER_OBJECT]
Expand Down

0 comments on commit 5444be2

Please sign in to comment.