-1

What is the best way to obtain the most accurate UTC time on windows in C++?

I am collecting samples which contains UTC time stamp and I need to validate if the sample is not older than one hour. I am using the system time, but what if someone modify it manually? Should I use some web service instead? If so, which would you recommend?

no one special
  • 1,608
  • 13
  • 32
  • 1
    Only an admin can change the system clock manually. Windows can be configured to sync the clock with a remote time server. Whenever the clock is adjusted, a notification is broadcasted to applications. – Remy Lebeau May 28 '16 at 08:58
  • 1
    This is not something you need to worry about. If a user is able to change the system time, they have already pwned the system, so it's game over for your app. [They are already on the other side of the airtight hatchway](https://blogs.msdn.microsoft.com/oldnewthing/20160107-00/?p=92801), which means they can just, for example, patch your binary to prevent the time check from occurring in the first place. Just query the system time. – Cody Gray - on strike May 28 '16 at 09:18

2 Answers2

2

If you want to be sure you have correct times, your best option is to query an NTP server. See the code samples here and here for a Windows C++ implementations.

Community
  • 1
  • 1
Ton Plooij
  • 2,583
  • 12
  • 15
  • 2
    ... but keep in mind that this won't work if you don't have a direct internet connection. Whether that is a problem depends on the scenario; if your application already depends on having direct internet access, it probably doesn't matter. – Harry Johnston May 28 '16 at 23:39
  • @HarryJohnston without internet connection, using a GPS dongle and a respective library to query it in your program might be a good solution to obtain a very precise time (keep in mind that the GPS timestamp does not include leap seconds though). – F1iX Jun 06 '18 at 12:25
  • @F1iX, good idea, but it depends on how many machines the software is running on. When I wrote my earlier comment I was probably assuming that the OP was talking about commercial or otherwise widely distributed software, though looking at the question again that may have been an unjustified assumption on my part. (I've spent a significant chunk of my working life over the past decade or two trying to wrangle software that just assumes everybody has direct internet access into working on machines that don't, so it's a bit of a sore spot!) – Harry Johnston Jun 07 '18 at 22:01
1

Thanks Ton Plooij for your links. Below I would like to share the code which finally worked well for me. Both functions provides UTC time in nanoseconds. First is based on system time, while the second performs query to NTP server time.

#include <winsock2.h>
#include <WS2tcpip.h>

#include <stdio.h>
#include <time.h>

time_t getTimeLocal()
{
    return 1000000000 * time(NULL);
}

time_t getTimeRemote()
{
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("200.20.186.76");
    server_addr.sin_port = htons(123);

    protoent *proto = getprotobyname("udp");
    int s = socket(PF_INET, SOCK_DGRAM, proto->p_proto);

    char msg[48] = { 0x08, 0, 0, 0, 0, 0, 0, 0, 0 };
    sendto(s, msg, sizeof(msg), 0, (struct sockaddr *) &server_addr, sizeof(server_addr));

    memset(msg, 0, sizeof(msg));
    struct sockaddr saddr;
    socklen_t saddr_l = sizeof(saddr);
    recvfrom(s, msg, 48, 0, &saddr, &saddr_l);

    closesocket(s);

    time_t rawtime = ntohl(*(u_long *) &msg[40]) - 2208988800U;
    return 1000000000 * rawtime;
}

int main()
{
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    printf("UTC time:\n");
    printf("system: %llu [nsec]\n", getTimeLocal());
    printf("server: %llu [nsec]\n", getTimeRemote());

    WSACleanup();
    getchar();
    return 0;
}
no one special
  • 1,608
  • 13
  • 32
  • You asked "What is the best way to obtain the *most accurate* UTC time". That doesn't seem to matter given given that you only need to detect more than an hour old, but just in case someone else is reading this... Reading an ntp server with the socket code above will give you a LESS accurate time than a properly configured Windows machine because part of the time protocol is an analysis of network latency. Your latency could be a few milliseconds to a few seconds, depending on traffic and bandwidth. One other thing - hard coding the IP address makes your code susceptible to server failures. – Jim Beveridge May 31 '16 at 19:45
  • Thank you for your hints. You are right, hard coding IP is bad idea for real application, but in above example is enough to keep is clear. And the same with the accuracy - from the example above I have removed socket configuration to wait max 500 msec for reply, which makes this quite accurate. My Windows is showing the difference within +/- 30 or above to the current time, which make it completely useless in my application, where I can accept up to 5 sec of such difference. – no one special Jun 02 '16 at 14:01
  • 1
    I looked it up and you are right. Windows is not designed to do high resolution time sync. A third party solution is required. http://stackoverflow.com/questions/27253216/configure-windows-time-with-high-sub-seconds-precision – Jim Beveridge Jun 03 '16 at 23:32
  • As discussed [here](https://stackoverflow.com/a/50719970/5885566), _ntp.flags.mode_ in `char msg[48] = {0x08,0,0,0,0,0,0,0,0};` and the buffer extraction position in `ntohl(*(u_long *) &msg[40])` may have to be changed depending on your needs. Btw, [NTPClient](https://github.com/ethanlim/NetworkTimeProtocol) is an elegant alternative for Windows using the boost libraries. – F1iX Jun 06 '18 at 12:21