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 machines 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.

Show a brief help listing, then exit with success status
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 the service pointing to the existing .EXE: it does not copy files anywhere, nor start the service.
Install the service as with -install, and then start it.
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.
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 through 9. 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.

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.
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.
This is just a helper module that supports printf-style access to OutputDebugString().
This defines the macros and extern definitions that cross module boundaries.
A GNU makefile (requires GNU make).
A Microsoft NMAKE-compatible makefile: just run nmake /f nmakefile to use this one.

The code is built by getting to a command window, putting MSVC (6 through 9) 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.

Netsh and the firewall

Port 37/tcp must be opened inbound on the machine running this service, and for machines with full Windows, this can be done in the GUI in the usual way, but for Hyper-V Server 2008 (and probably Server 2008 Core), which have no meaningful GUI, one must use the command line to manage the firewall.

We prefer to whitelist the program rather than the port but are not sure this is the best approach (feedback welcome).

From a CMD prompt, this should be run all on a single line:

C> netsh advfirewall firewall add rule
    name=" RFC868 time service"

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.

Version Histroy

v1.5 - 2011/03/05
  • Now enable DEP, ASLR, and the /GS stack checking parameter in the makefile for security
  • Added a proper description that shows up in the Services control-panel applet
  • Built and tested with Visual Studio 2008
  • Added the -installstart command-line option to install and start the service
  • The service now drops all local privileges once the network port has been created, but before it has accepted any data.
  • Version tested on Win2000, Server 2003, Server 2008 R2, and Win7

First published: 2007/08/04