[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