[Git][NTPsec/ntpsec][master] 2 commits: First successful authenticated Mode 6 send from Python.
Eric S. Raymond
gitlab at mg.gitlab.com
Tue Nov 1 09:33:04 UTC 2016
Eric S. Raymond pushed to branch master at NTPsec / ntpsec
Commits:
9e6850db by Eric S. Raymond at 2016-10-31T22:45:37-04:00
First successful authenticated Mode 6 send from Python.
- - - - -
401a8ef4 by Eric S. Raymond at 2016-11-01T05:31:16-04:00
In pyntpq, ship authenticated :config and handle responses.
- - - - -
3 changed files:
- docs/mode6.txt
- ntpq/pyntpq
- pylib/packet.py
Changes:
=====================================
docs/mode6.txt
=====================================
--- a/docs/mode6.txt
+++ b/docs/mode6.txt
@@ -220,9 +220,13 @@ The response payload is a textual varlist.
This request is used to change the configuration of ntpd without
restarting the daemon. It requires authentication.
-The request payload should be a line of text in the syntax of the
-ntp.conf configuration file. The response payload will be either
-an error message or the string "Config Succeeded".
+The request payload should be a line line of text in the syntax of the
+ntp.conf configuration file. The response payload will begin with either
+an error message or the string "Config Succeeded", followed by a NUL.
+
+Note: Due to an implementation error, the response packet may and
+typically will contain trailing garbage. Implementations should
+expect this and truncate it at the first NUL.
=== CTL_OP_READ_MRU ===
=====================================
ntpq/pyntpq
=====================================
--- a/ntpq/pyntpq
+++ b/ntpq/pyntpq
@@ -8,7 +8,7 @@
# SPDX-License-Identifier: BSD-2-clause
from __future__ import print_function, division
-import os, sys, getopt, cmd, errno, curses, curses.ascii
+import os, sys, getopt, cmd, errno, curses, curses.ascii, re
import socket, select, struct, shlex, time, hashlib
from ntp.packet import *
@@ -1138,7 +1138,23 @@ usage: lopeers
def do_config(self, line):
"send a remote configuration command to ntpd"
- self.say(self.session.config(line) + "\n")
+ if self.debug > 2:
+ self.warn("In Config\nKeyword = :config\nCommand = %s\n" % line)
+ try:
+ response = self.session.config(line)
+ m = re.match("column ([0-9]+) syntax error", response)
+ if m:
+ col = int(m.group(1))
+ if col >= 0 and col <= len(line):
+ if self.interactive:
+ self.say("_" * (len(self.prompt) + 2 + col))
+ else:
+ self.say(line + "\n")
+ self.say("_" * (col- 1))
+ self.say("^\n")
+ self.say(response + "\n")
+ except Mode6Exception as e:
+ print(e.message)
def help_config(self):
self.say("""\
=====================================
pylib/packet.py
=====================================
--- a/pylib/packet.py
+++ b/pylib/packet.py
@@ -178,7 +178,7 @@ class Mode6Packet(Packet):
def __init__(self, session, opcode=0, associd=0, qdata=''):
Packet.__init__(self, session, session.pktversion, MODE_CONTROL)
self.r_e_m_op = opcode # ntpq operation code
- self.sequence = 0 # sequence number of request (uint16_t)
+ self.sequence = 1 # sequence number of request (uint16_t)
self.status = 0 # status word for association (uint16_t)
self.associd = associd # association ID (uint16_t)
self.offset = 0 # offset of this batch of data (uint16_t)
@@ -251,6 +251,7 @@ SERR_BADLENGTH = "***Response length should have been a multiple of 4"
SERR_BADKEY = "***Invalid key identifier"
SERR_INVPASS = "***Invalid password"
SERR_NOKEY = "***Key not found"
+SERR_AUTH = "***Server disallowed request (authentication?)"
def dump_hex_printable(xdata):
"Dump a packet in hex, in a familiar hex format"
@@ -414,10 +415,8 @@ class Mode6Session:
if pkt.extension:
pkt.extension = polybytes(pkt.extension)
while ((Packet.HEADER_LEN + len(pkt.extension)) & 3):
- print("Adding pad byte")
pkt.extension += b"\x00"
pkt.extension = polystr(pkt.extension)
- print("Length after early padding: %d" % (Packet.HEADER_LEN + len(pkt.extension)))
# If it isn't authenticated we can just send it. Otherwise
# we're going to have to think about it a little.
@@ -450,6 +449,7 @@ class Mode6Session:
# Do the encryption.
hasher = hashlib.new(self.keytype)
+ hasher.update(self.passwd)
hasher.update(pkt.flatten());
if hasher.digest_size == 0:
raise Mode6Exception(SERR_NOKEY)
@@ -666,7 +666,7 @@ class Mode6Session:
self.doquery(opcode, associd=associd, qdata=qdata)
response = self.response
# Trim trailing NULs from the text
- while response.endswith("\x00"):
+ while response.endswith(b"\x00"):
response = response[:-1]
response = response.rstrip()
items = []
@@ -694,6 +694,12 @@ class Mode6Session:
def config(self, configtext):
"Send configuration text to the daemon."
self.doquery(opcode=CTL_OP_CONFIGURE, qdata=configtext, auth=True)
- return self.response
+ # Copes with an implementation error - ntpd uses putdata without
+ # setting the size correctly.
+ if not self.response:
+ raise Mode6Exception(SERR_AUTH)
+ elif b"\x00" in self.response:
+ self.response = self.response[:self.response.index(b"\x00")]
+ return self.response.rstrip()
# end
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/compare/2062c8d0a7a3c444e1ec1b9f27ef998c78b1388b...401a8ef4f630fae9f79817e1613e633ad0ad616d
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ntpsec.org/pipermail/vc/attachments/20161101/0673827e/attachment.html>
More information about the vc
mailing list