void test_GenerateAuthenticatedPacket(void) { static const int EXPECTED_PKTLEN = LEN_PKT_NOMAC + MAX_MD5_LEN; struct key testkey; struct pkt testpkt; struct timeval xmt; l_fp expected_xmt, actual_xmt; char expected_mac[MAX_MD5_LEN]; testkey.next = NULL; testkey.key_id = 30; testkey.key_len = 9; memcpy(testkey.key_seq, "123456789", testkey.key_len); strlcpy(testkey.typen, "MD5", sizeof(testkey.typen)); testkey.typei = keytype_from_text(testkey.typen, NULL); GETTIMEOFDAY(&xmt, NULL); xmt.tv_sec += JAN_1970; TEST_ASSERT_EQUAL(EXPECTED_PKTLEN, generate_pkt(&testpkt, &xmt, testkey.key_id, &testkey)); TEST_ASSERT_EQUAL(LEAP_NOTINSYNC, PKT_LEAP(testpkt.li_vn_mode)); TEST_ASSERT_EQUAL(NTP_VERSION, PKT_VERSION(testpkt.li_vn_mode)); TEST_ASSERT_EQUAL(MODE_CLIENT, PKT_MODE(testpkt.li_vn_mode)); TEST_ASSERT_EQUAL(STRATUM_UNSPEC, PKT_TO_STRATUM(testpkt.stratum)); TEST_ASSERT_EQUAL(8, testpkt.ppoll); TVTOTS(&xmt, &expected_xmt); NTOHL_FP(&testpkt.xmt, &actual_xmt); TEST_ASSERT_TRUE(LfpEquality(expected_xmt, actual_xmt)); TEST_ASSERT_EQUAL(testkey.key_id, ntohl(testpkt.exten[0])); TEST_ASSERT_EQUAL(MAX_MD5_LEN - 4, /* Remove the key_id, only keep the mac. */ make_mac(&testpkt, LEN_PKT_NOMAC, MAX_MD5_LEN-4, &testkey, expected_mac)); TEST_ASSERT_EQUAL_MEMORY(expected_mac, (char*)&testpkt.exten[1], MAX_MD5_LEN -4); }
/* ** xmt() */ void xmt( xmt_ctx * xctx ) { SOCKET sock = xctx->sock; struct dns_ctx *dctx = xctx->spkt->dctx; sent_pkt * spkt = xctx->spkt; sockaddr_u * dst = &spkt->addr; struct timeval tv_xmt; struct pkt x_pkt; size_t pkt_len; int sent; if (0 != gettimeofday(&tv_xmt, NULL)) { msyslog(LOG_ERR, "xmt: gettimeofday() failed: %m"); exit(1); } tv_xmt.tv_sec += JAN_1970; pkt_len = generate_pkt(&x_pkt, &tv_xmt, dctx->key_id, dctx->key); sent = sendpkt(sock, dst, &x_pkt, pkt_len); if (sent) { /* Save the packet we sent... */ memcpy(&spkt->x_pkt, &x_pkt, min(sizeof(spkt->x_pkt), pkt_len)); spkt->stime = tv_xmt.tv_sec - JAN_1970; TRACE(2, ("xmt: %lx.%6.6u %s %s\n", (u_long)tv_xmt.tv_sec, (u_int)tv_xmt.tv_usec, dctx->name, stoa(dst))); } else { dec_pending_ntp(dctx->name, dst); } return; }
TEST_F(mainTest, GenerateUnauthenticatedPacket) { pkt testpkt; timeval xmt; GETTIMEOFDAY(&xmt, NULL); xmt.tv_sec += JAN_1970; EXPECT_EQ(LEN_PKT_NOMAC, generate_pkt(&testpkt, &xmt, 0, NULL)); EXPECT_EQ(LEAP_NOTINSYNC, PKT_LEAP(testpkt.li_vn_mode)); EXPECT_EQ(NTP_VERSION, PKT_VERSION(testpkt.li_vn_mode)); EXPECT_EQ(MODE_CLIENT, PKT_MODE(testpkt.li_vn_mode)); EXPECT_EQ(STRATUM_UNSPEC, PKT_TO_STRATUM(testpkt.stratum)); EXPECT_EQ(8, testpkt.ppoll); l_fp expected_xmt, actual_xmt; TVTOTS(&xmt, &expected_xmt); NTOHL_FP(&testpkt.xmt, &actual_xmt); EXPECT_TRUE(LfpEquality(expected_xmt, actual_xmt)); }
TEST_F(mainTest, GenerateAuthenticatedPacket) { key testkey; testkey.next = NULL; testkey.key_id = 30; testkey.key_len = 9; memcpy(testkey.key_seq, "123456789", testkey.key_len); memcpy(testkey.type, "MD5", 3); pkt testpkt; timeval xmt; GETTIMEOFDAY(&xmt, NULL); xmt.tv_sec += JAN_1970; const int EXPECTED_PKTLEN = LEN_PKT_NOMAC + MAX_MD5_LEN; EXPECT_EQ(EXPECTED_PKTLEN, generate_pkt(&testpkt, &xmt, testkey.key_id, &testkey)); EXPECT_EQ(LEAP_NOTINSYNC, PKT_LEAP(testpkt.li_vn_mode)); EXPECT_EQ(NTP_VERSION, PKT_VERSION(testpkt.li_vn_mode)); EXPECT_EQ(MODE_CLIENT, PKT_MODE(testpkt.li_vn_mode)); EXPECT_EQ(STRATUM_UNSPEC, PKT_TO_STRATUM(testpkt.stratum)); EXPECT_EQ(8, testpkt.ppoll); l_fp expected_xmt, actual_xmt; TVTOTS(&xmt, &expected_xmt); NTOHL_FP(&testpkt.xmt, &actual_xmt); EXPECT_TRUE(LfpEquality(expected_xmt, actual_xmt)); EXPECT_EQ(testkey.key_id, ntohl(testpkt.exten[0])); char expected_mac[MAX_MD5_LEN]; ASSERT_EQ(MAX_MD5_LEN - 4, // Remove the key_id, only keep the mac. make_mac((char*)&testpkt, LEN_PKT_NOMAC, MAX_MD5_LEN, &testkey, expected_mac)); EXPECT_TRUE(memcmp(expected_mac, (char*)&testpkt.exten[1], MAX_MD5_LEN -4) == 0); }
void test_GenerateUnauthenticatedPacket(void) { struct pkt testpkt; struct timeval xmt; l_fp expected_xmt, actual_xmt; GETTIMEOFDAY(&xmt, NULL); xmt.tv_sec += JAN_1970; TEST_ASSERT_EQUAL(LEN_PKT_NOMAC, generate_pkt(&testpkt, &xmt, 0, NULL)); TEST_ASSERT_EQUAL(LEAP_NOTINSYNC, PKT_LEAP(testpkt.li_vn_mode)); TEST_ASSERT_EQUAL(NTP_VERSION, PKT_VERSION(testpkt.li_vn_mode)); TEST_ASSERT_EQUAL(MODE_CLIENT, PKT_MODE(testpkt.li_vn_mode)); TEST_ASSERT_EQUAL(STRATUM_UNSPEC, PKT_TO_STRATUM(testpkt.stratum)); TEST_ASSERT_EQUAL(8, testpkt.ppoll); TVTOTS(&xmt, &expected_xmt); NTOHL_FP(&testpkt.xmt, &actual_xmt); TEST_ASSERT_TRUE(LfpEquality(expected_xmt, actual_xmt)); }
/* The heart of (S)NTP, exchange NTP packets and compute values to correct the local clock */ int on_wire ( struct addrinfo *host, struct addrinfo *bcast ) { char addr_buf[INET6_ADDRSTRLEN]; register int try; SOCKET sock; struct key *pkt_key = NULL; int key_id = 0; struct timeval tv_xmt; struct pkt x_pkt; int error, rpktl, handle_pkt_res; if (ENABLED_OPT(AUTHENTICATION)) { key_id = (int) atol(OPT_ARG(AUTHENTICATION)); get_key(key_id, &pkt_key); } for (try=0; try<5; try++) { memset(&r_pkt, 0, sizeof rbuf); error = GETTIMEOFDAY(&tv_xmt, (struct timezone *)NULL); tv_xmt.tv_sec += JAN_1970; #ifdef DEBUG printf("sntp on_wire: Current time sec: %i msec: %i\n", (unsigned int) tv_xmt.tv_sec, (unsigned int) tv_xmt.tv_usec); #endif if (bcast) { create_socket(&sock, (sockaddr_u *)bcast->ai_addr); rpktl = recv_bcst_pkt(sock, &r_pkt, sizeof rbuf, (sockaddr_u *)bcast->ai_addr); closesocket(sock); } else { int pkt_len = generate_pkt(&x_pkt, &tv_xmt, key_id, pkt_key); create_socket(&sock, (sockaddr_u *)host->ai_addr); sendpkt(sock, (sockaddr_u *)host->ai_addr, &x_pkt, pkt_len); rpktl = recvpkt(sock, &r_pkt, sizeof rbuf, &x_pkt); closesocket(sock); } handle_pkt_res = handle_pkt(rpktl, &r_pkt, host); if (handle_pkt_res < 1) return handle_pkt_res; } getnameinfo(host->ai_addr, host->ai_addrlen, addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST); msyslog(LOG_DEBUG, "Received no useable packet from %s!", addr_buf); return -1; } /* Compute the 8 bits for li_vn_mode */ void set_li_vn_mode ( struct pkt *spkt, char leap, char version, char mode ) { if (leap > 3) { msyslog(LOG_DEBUG, "set_li_vn_mode: leap > 3 using max. 3"); leap = 3; } if (mode > 7) { msyslog(LOG_DEBUG, "set_li_vn_mode: mode > 7, using client mode 3"); mode = 3; } spkt->li_vn_mode = leap << 6; spkt->li_vn_mode |= version << 3; spkt->li_vn_mode |= mode; } /* set_time corrects the local clock by offset with either settimeofday() or by default * with adjtime()/adjusttimeofday(). */ int set_time( double offset ) { struct timeval tp; if (ENABLED_OPT(SETTOD)) { GETTIMEOFDAY(&tp, NULL); tp.tv_sec += (long)offset; tp.tv_usec += 1e6 * (offset - (long)offset); NORMALIZE_TIMEVAL(tp); if (SETTIMEOFDAY(&tp, NULL) < 0) { msyslog(LOG_ERR, "Time not set: settimeofday(): %m"); return -1; } return 0; } tp.tv_sec = (long)offset; tp.tv_usec = 1e6 * (offset - (long)offset); NORMALIZE_TIMEVAL(tp); if (ADJTIMEOFDAY(&tp, NULL) < 0) { msyslog(LOG_ERR, "Time not set: adjtime(): %m"); return -1; } return 0; }