Does this site look plain?

This site uses advanced css techniques

The Network Time Protocol is often used to synchronize the system clocks across an enterprise, but it's remarkably easy for this to get out of whack: a service didn't start, a firewall didn't allow the NTP traffic, or a configuration file was wrong. These can cause failures of time synchronization without really knowing about it.

Table of Contents

Faced with this problem on our own network, we set out to create a time auditing system that checks the time on all the machines in the enterprise, and reports deviations found. This is done using the RFC 868 Time Protocol.

RFC868 protocol exchange This is an utterly simple client/server protocol: the client connects to the server over port 37/tcp, the server writes the current UNIX time, then closes the connection. There is no real handshake, and the client doesn't say anything — it only listens. Since it's in UNIX time relative to GMT, there are no timezone issues to worry about.

A small bit of perl code can easily cycle through a series of machine looking for deviation from the norm. This time protocol is supported by all UNIX and Linux systems, but not on Windows, so we created a system service to perform this task. This page documents our efforts.

Download the Code

This tool is offered in both source and binary form. The source is provided in a ZIP file containing the C++ files, and the binary is a standard Windows .EXE. Both the source and the .EXE are less than 20 kbytes each, reflecting our byte-frugal approach to coding.

Note that these files include the version number in the name: it should probably be renamed to remove this upon downloading.

We promise that the binary was built from this very source, and that it contains no shenanigans. We do not promise that it has no bugs: you have to decide for yourself which of these claims you care to trust.

Installing / Uninstalling

The service consists of a single executable — rfc868time.exe — that should be manually installed to the final location from where it will run. We normally choose the c:\bin\ directory, but the software doesn't care where it goes.

Once it's in place, it's installed as an auto-start service with the -install parameter. This doesn't copy any files, but merely makes an entry into the Services database pointing to the current .EXE:

C> mkdir \bin
C> xcopy C:\some\other\place\rfc868time.exe
C> rfc868time -install

This does not start the service, but it can be done from the command line as well:

C> net start rfc868time

It can also be started and stopped from the usual Services applet in the control panel:

rfc868time in the Services applet

This code is known to run on Windows XP, Windows 2000, and Server 2003.

Command Line Parameters

This program is not normally expected to be run with any command-line parameters, but when installing, removing, or testing, there are a few which might be useful. This is strictly a console-mode application, so these aren't really too interesting unless run from a command window.

-help
Show a brief help listing, then exit with success status
-version
Show the program's version information, then exit. Most of our tools report their version information in a specific way to support automatic deployment of new versions to the website.
-install
Install the service pointing to the existing .EXE: it does not copy files anywhere, nor start the service.
-remove
Stop the service (if necessary), then uninstall the service. This only removes this program from the Services database, and it does not remove the file itself.
-debug
This enables a bit more debugging output to the OutputDebugString debugging channel; only really useful for developers working with the source.

Querying the time service

The service has essentially no footprint on the machine itself, but it is visible on the network from other systems. Many Unix/Linux variants provide the rdate command which queries a service on another machine, and this can be used to check the time across the network from a central location.

Running this command on our Linux system to query the rfc868time service running on wiz, our XP desktop, as well as the local Linux system, we see:

$ rdate localhost wiz
rdate: [localhost]      Sat Aug  4 16:44:08 2007

rdate: [wiz]    Sat Aug  4 16:44:08 2007

Note that the time provided by the protocol is in GMT, and the conversion to local time is done by the rdate command: the rfc868time service has no knowledge of timezones.

As many hosts can be provided as desired, and this can be scripted with the shell or with some perl code to do this systematically. We have used such a system in a number of enterprises to allow auditing of time synchronization throughout the network, but have not yet packaged it up for release. It's on our list.

The Source Code

This is a traditional Windows service, administered from the Services applet in the control panel. It's normally set to auto-start, and then forgotten: it takes essentially no CPU time when not being used, and has no tunable parameters.

It's written in C++ and compiles cleanly with MSVC 6 or 7. It does not use a Visual Studio project file: we do all our Win32 development with vi and make from the command line.

The code should compile without errors or warnings.

rfc868time.cpp
This is the main module, the one that knows the details about the purpose for this service ("time"). It defers on the housekeeping functions for being a service to the following module.
service.cpp
This is a module we use for all services we write, and it's relatively generic. It handles all interactions with the Service Controller, including install and remove. This is relatively easy to adapt to some other service, allowing the main module to worry about its intended functionality without getting bogged down with the Services API.
odprintf.cpp
This is just a helper module that supports printf-style access to OutputDebugString().
defs.h
This defines the macros and extern definitions that cross module boundaries.
makefile
A Microsoft NMAKE-compatible makefile.

The code is built by getting to a command window, putting MSVC (6 or 7) in the %PATH%, and typing "make": the resultant rfc868time.exe can be copied to the desired final location, installed, and started.

Security concerns

This code runs as a service and provides an exposed network port: this clearly increases the attack surface of a system and warrants some serious investigation as to whether it's a risk to employ this. We don't think it is.

First, this code accepts no data from the network: it accepts a connection, but then writes some bytes and closes the socket. Since there is no input buffer, there is no buffer to overflow.

Second, it does no inverse DNS lookups on the connecting IP address, so it cannot be gamed by a bad guy who controls the nameservers by passing malformed or overly large data in a PTR record.

The only potential vector we see is that of a DoS attack, as this code has no provisions for connection rate limiting or controlling access to just a limited set of IP addresses. But this is general problem of most services of this type, and not a security weakness of this code per se.

We have never exposed this service to the internet and would probably recommend against it on general principles.

Bugs and Things Undone

The code is now working quite well on at least a dozen systems, but there is always more to be done.


First published: 2007/08/04