void test_CorrectUnauthenticatedPacket(void) { TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); TEST_ASSERT_EQUAL(LEN_PKT_NOMAC, process_pkt(&testpkt, &testsock, LEN_PKT_NOMAC, MODE_SERVER, &testspkt, "UnitTest")); }
/* Fetch data, check if it's data for us and whether it's useable or not. If not, return * a failure code so we can delete this server from our list and continue with another one. */ int recvpkt ( SOCKET rsock, struct pkt *rpkt, /* received packet (response) */ unsigned int rsize, /* size of rpkt buffer */ struct pkt *spkt /* sent packet (request) */ ) { int rdy_socks; int pkt_len; sockaddr_u sender; struct timeval timeout_tv; fd_set recv_fd; FD_ZERO(&recv_fd); FD_SET(rsock, &recv_fd); if (ENABLED_OPT(TIMEOUT)) timeout_tv.tv_sec = (int) atol(OPT_ARG(TIMEOUT)); else timeout_tv.tv_sec = 68; /* ntpd broadcasts every 64s */ timeout_tv.tv_usec = 0; rdy_socks = select(rsock + 1, &recv_fd, 0, 0, &timeout_tv); switch (rdy_socks) { case -1: if (ENABLED_OPT(NORMALVERBOSE)) perror("sntp recvpkt: select()"); return PACKET_UNUSEABLE; break; case 0: if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recvpkt: select() reached timeout (%u sec), aborting.\n", (unsigned)timeout_tv.tv_sec); return PACKET_UNUSEABLE; break; default: break; } pkt_len = recvdata(rsock, &sender, (char *)rpkt, rsize); if (pkt_len > 0) pkt_len = process_pkt(rpkt, &sender, pkt_len, MODE_SERVER, spkt, "recvpkt"); return pkt_len; }
void test_KoDDeny(void) { TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); testpkt.stratum = STRATUM_PKT_UNSPEC; memcpy(&testpkt.refid, "DENY", 4); TEST_ASSERT_EQUAL(KOD_DEMOBILIZE, process_pkt(&testpkt, &testsock, LEN_PKT_NOMAC, MODE_SERVER, &testspkt, "UnitTest")); }
void test_RejectUnsyncedServer(void) { TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); testpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC, NTP_VERSION, MODE_SERVER); TEST_ASSERT_EQUAL(SERVER_UNUSEABLE, process_pkt(&testpkt, &testsock, LEN_PKT_NOMAC, MODE_SERVER, &testspkt, "UnitTest")); }
static void generate_request (void) { gnutls_datum_t dat; _generate_request(load_cert(), load_issuer(), &dat, ENABLED_OPT(NONCE)); fwrite (dat.data, 1, dat.size, outfile); gnutls_free (dat.data); }
void test_AcceptNoSentPacketBroadcastMode(void) { TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); testpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION, MODE_BROADCAST); TEST_ASSERT_EQUAL(LEN_PKT_NOMAC, process_pkt(&testpkt, &testsock, LEN_PKT_NOMAC, MODE_BROADCAST, NULL, "UnitTest")); }
/* Creates a socket and returns. */ void create_socket ( SOCKET *rsock, sockaddr_u *dest ) { *rsock = socket(AF(dest), SOCK_DGRAM, 0); if (-1 == *rsock && ENABLED_OPT(NORMALVERBOSE)) printf("Failed to create UDP socket with family %d\n", AF(dest)); }
void test_CryptoNAKPacketReject(void) { // Activate authentication option ActivateOption("-a", "123"); TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); int pkt_len = LEN_PKT_NOMAC + 4; // + 4 byte MAC = Crypto-NAK TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL, process_pkt(&testpkt, &testsock, pkt_len, MODE_SERVER, &testspkt, "UnitTest")); }
int main(int argc, char **argv) { int ret; if ((ret = gnutls_global_init()) < 0) { fprintf(stderr, "global_init: %s\n", gnutls_strerror(ret)); exit(1); } optionProcess(&ocsptoolOptions, argc, argv); gnutls_global_set_log_function(tls_log_func); gnutls_global_set_log_level(OPT_VALUE_DEBUG); if (HAVE_OPT(OUTFILE)) { outfile = fopen(OPT_ARG(OUTFILE), "wb"); if (outfile == NULL) { fprintf(stderr, "%s\n", OPT_ARG(OUTFILE)); exit(1); } } else outfile = stdout; if (HAVE_OPT(INFILE)) { infile = fopen(OPT_ARG(INFILE), "rb"); if (infile == NULL) { fprintf(stderr, "%s\n", OPT_ARG(INFILE)); exit(1); } } else infile = stdin; if (ENABLED_OPT(INDER)) encoding = GNUTLS_X509_FMT_DER; else encoding = GNUTLS_X509_FMT_PEM; if (HAVE_OPT(REQUEST_INFO)) request_info(); else if (HAVE_OPT(RESPONSE_INFO)) response_info(); else if (HAVE_OPT(GENERATE_REQUEST)) generate_request(NULL); else if (HAVE_OPT(VERIFY_RESPONSE)) verify_response(NULL); else if (HAVE_OPT(ASK)) ask_server(OPT_ARG(ASK)); else { USAGE(1); } return 0; }
static void ask_server(const char *url) { gnutls_datum_t resp_data; int ret, v = 0; gnutls_x509_crt_t cert, issuer; unsigned char noncebuf[23]; gnutls_datum_t nonce = { noncebuf, sizeof(noncebuf) }; gnutls_datum_t *n; cert = load_cert(); issuer = load_issuer(); if (ENABLED_OPT(NONCE)) { ret = gnutls_rnd(GNUTLS_RND_NONCE, nonce.data, nonce.size); if (ret < 0) { fprintf(stderr, "gnutls_rnd: %s\n", gnutls_strerror(ret)); exit(1); } n = &nonce; } else { n = NULL; } ret = send_ocsp_request(url, cert, issuer, &resp_data, n); if (ret < 0) { fprintf(stderr, "Cannot send OCSP request\n"); exit(1); } _response_info(&resp_data); if (HAVE_OPT(LOAD_TRUST)) { v = _verify_response(&resp_data, n, NULL); } else if (HAVE_OPT(LOAD_SIGNER)) { v = _verify_response(&resp_data, n, load_signer()); } else { fprintf(stderr, "\nAssuming response's signer = issuer (use --load-signer to override).\n"); v = _verify_response(&resp_data, n, issuer); } if (HAVE_OPT(OUTFILE) && (v == 0 || HAVE_OPT(IGNORE_ERRORS))) { fwrite(resp_data.data, 1, resp_data.size, outfile); } if (v && !HAVE_OPT(IGNORE_ERRORS)) exit(1); }
TEST_F(mainTest, HandleCorrectPacket) { pkt rpkt; sockaddr_u host; int rpktl; l_fp now; // We don't want our testing code to actually change the system clock. ASSERT_FALSE(ENABLED_OPT(STEP)); ASSERT_FALSE(ENABLED_OPT(SLEW)); get_systime(&now); HTONL_FP(&now, &rpkt.reftime); HTONL_FP(&now, &rpkt.org); HTONL_FP(&now, &rpkt.rec); HTONL_FP(&now, &rpkt.xmt); rpktl = LEN_PKT_NOMAC; ZERO(host); AF(&host) = AF_INET; EXPECT_EQ(0, handle_pkt(rpktl, &rpkt, &host, "")); }
static unsigned opt_to_flags(void) { unsigned flags = 0; if (HAVE_OPT(MARK_PRIVATE)) { if (ENABLED_OPT(MARK_PRIVATE)) { flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE; } else { flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE; } } if (ENABLED_OPT(MARK_TRUSTED)) flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED; if (ENABLED_OPT(MARK_CA)) flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_CA; if (ENABLED_OPT(MARK_WRAP)) flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP; if (ENABLED_OPT(LOGIN)) flags |= GNUTLS_PKCS11_OBJ_FLAG_LOGIN; if (ENABLED_OPT(SO_LOGIN)) flags |= GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO; return flags; }
/* ** handle_lookup */ void handle_lookup( const char *name, int flags ) { struct addrinfo hints; /* Local copy is OK */ struct dns_ctx *ctx; char * name_copy; size_t name_sz; size_t octets; TRACE(1, ("handle_lookup(%s,%#x)\n", name, flags)); ZERO(hints); hints.ai_family = ai_fam_pref; hints.ai_flags = AI_CANONNAME | Z_AI_NUMERICSERV; /* ** Unless we specify a socktype, we'll get at least two ** entries for each address: one for TCP and one for ** UDP. That's not what we want. */ hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; name_sz = 1 + strlen(name); octets = sizeof(*ctx) + name_sz; // Space for a ctx and the name ctx = emalloc_zero(octets); // ctx at ctx[0] name_copy = (char *)(ctx + 1); // Put the name at ctx[1] memcpy(name_copy, name, name_sz); // copy the name to ctx[1] ctx->name = name_copy; // point to it... ctx->flags = flags; ctx->timeout = response_tv; ctx->key = NULL; /* The following should arguably be passed in... */ if (ENABLED_OPT(AUTHENTICATION)) { ctx->key_id = OPT_VALUE_AUTHENTICATION; get_key(ctx->key_id, &ctx->key); if (NULL == ctx->key) { fprintf(stderr, "%s: Authentication with keyID %d requested, but no matching keyID found in <%s>!\n", progname, ctx->key_id, OPT_ARG(KEYFILE)); exit(1); } } else { ctx->key_id = -1; } ++n_pending_dns; getaddrinfo_sometime(name, "123", &hints, 0, &sntp_name_resolved, ctx); }
void test_NonWantedMode(void) { TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); testpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION, MODE_CLIENT); // The packet has a mode of MODE_CLIENT, but process_pkt expects MODE_SERVER TEST_ASSERT_EQUAL(SERVER_UNUSEABLE, process_pkt(&testpkt, &testsock, LEN_PKT_NOMAC, MODE_SERVER, &testspkt, "UnitTest")); }
void test_UnauthenticatedPacketReject(void) { //sntptest(); // Activate authentication option ActivateOption("-a", "123"); TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); int pkt_len = LEN_PKT_NOMAC; // We demand authentication, but no MAC header is present. TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL, process_pkt(&testpkt, &testsock, pkt_len, MODE_SERVER, &testspkt, "UnitTest")); }
void test_ServerVersionTooNew(void) { TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); testpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION + 1, MODE_CLIENT); TEST_ASSERT_TRUE(PKT_VERSION(testpkt.li_vn_mode) > NTP_VERSION); int pkt_len = LEN_PKT_NOMAC; TEST_ASSERT_EQUAL(SERVER_UNUSEABLE, process_pkt(&testpkt, &testsock, pkt_len, MODE_SERVER, &testspkt, "UnitTest")); }
void test_HandleCorrectPacket(void) { struct pkt rpkt; sockaddr_u host; int rpktl; l_fp now; /* We don't want our testing code to actually change the system clock. */ TEST_ASSERT_FALSE(ENABLED_OPT(STEP)); TEST_ASSERT_FALSE(ENABLED_OPT(SLEW)); get_systime(&now); HTONL_FP(&now, &rpkt.reftime); HTONL_FP(&now, &rpkt.org); HTONL_FP(&now, &rpkt.rec); HTONL_FP(&now, &rpkt.xmt); rpktl = LEN_PKT_NOMAC; ZERO(host); AF(&host) = AF_INET; TEST_ASSERT_EQUAL(0, handle_pkt(rpktl, &rpkt, &host, "")); }
static FILE* open_ag_file(char ** pzBase) { switch (WHICH_IDX_AUTOGEN) { case INDEX_OPT_OUTPUT: { static char const zFileFmt[] = " * %s\n"; FILE* fp; if (*pzBase != NULL) free(*pzBase); if (strcmp(OPT_ARG(OUTPUT), "-") == 0) return stdout; unlink(OPT_ARG(OUTPUT)); fp = fopen(OPT_ARG(OUTPUT), "w" FOPEN_BINARY_FLAG); fprintf(fp, zDne, OPT_ARG(OUTPUT)); if (HAVE_OPT(INPUT)) { int ct = STACKCT_OPT(INPUT); char const ** ppz = STACKLST_OPT(INPUT); do { fprintf(fp, zFileFmt, *ppz++); } while (--ct > 0); } fputs(" */\n", fp); return fp; } case INDEX_OPT_AUTOGEN: if (! ENABLED_OPT(AUTOGEN)) { if (*pzBase != NULL) free(*pzBase); return stdout; } if ( ( OPT_ARG(AUTOGEN) != NULL) && (*OPT_ARG(AUTOGEN) != NUL )) pzAutogen = OPT_ARG(AUTOGEN); break; } return NULL; }
void test_RejectWrongResponseServerMode(void) { TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); l_fp tmp; tmp.l_ui = 1000UL; tmp.l_uf = 0UL; HTONL_FP(&tmp, &testpkt.org); tmp.l_ui = 2000UL; tmp.l_uf = 0UL; HTONL_FP(&tmp, &testspkt.xmt); TEST_ASSERT_EQUAL(PACKET_UNUSEABLE, process_pkt(&testpkt, &testsock, LEN_PKT_NOMAC, MODE_SERVER, &testspkt, "UnitTest")); }
void test_CorrectAuthenticatedPacketSHA1(void) { PrepareAuthenticationTest(20, 15, "SHA1", "abcdefghijklmno"); TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); int pkt_len = LEN_PKT_NOMAC; // Prepare the packet. testpkt.exten[0] = htonl(20); int mac_len = make_mac((char*)&testpkt, pkt_len, MAX_MAC_LEN, key_ptr, (char*)&testpkt.exten[1]); pkt_len += 4 + mac_len; TEST_ASSERT_EQUAL(pkt_len, process_pkt(&testpkt, &testsock, pkt_len, MODE_SERVER, &testspkt, "UnitTest")); }
void test_AuthenticatedPacketUnknownKey(void) { // Activate authentication option PrepareAuthenticationTestMD5(30, 9, "123456789"); TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); // Prepare the packet. Observe that the Key-ID expected is 30, // but the packet has a key id of 50. int pkt_len = LEN_PKT_NOMAC; testpkt.exten[0] = htonl(50); int mac_len = make_mac((char*)&testpkt, pkt_len, MAX_MD5_LEN, key_ptr, (char*)&testpkt.exten[1]); pkt_len += 4 + mac_len; TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL, process_pkt(&testpkt, &testsock, pkt_len, MODE_SERVER, &testspkt, "UnitTest")); }
void test_CorrectAuthenticatedPacketMD5(void) { PrepareAuthenticationTestMD5(10, 15, "123456789abcdef"); TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); int pkt_len = LEN_PKT_NOMAC; /* Prepare the packet. */ testpkt.exten[0] = htonl(10); int mac_len = make_mac(&testpkt, pkt_len, MAX_MD5_LEN, key_ptr, &testpkt.exten[1]); pkt_len += 4 + mac_len; TEST_ASSERT_EQUAL(pkt_len, process_pkt(&testpkt, &testsock, pkt_len, MODE_SERVER, &testspkt, "UnitTest")); }
static void _response_info(const gnutls_datum_t * data) { gnutls_ocsp_resp_t resp; int ret; gnutls_datum buf; ret = gnutls_ocsp_resp_init(&resp); if (ret < 0) { fprintf(stderr, "ocsp_resp_init: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_ocsp_resp_import(resp, data); if (ret < 0) { fprintf(stderr, "importing response: %s\n", gnutls_strerror(ret)); exit(1); } if (ENABLED_OPT(VERBOSE)) ret = gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &buf); else ret = gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_COMPACT, &buf); if (ret != 0) { fprintf(stderr, "ocsp_resp_print: %s\n", gnutls_strerror(ret)); exit(1); } printf("%.*s", buf.size, buf.data); gnutls_free(buf.data); gnutls_ocsp_resp_deinit(resp); }
void test_AuthenticatedPacketInvalid(void) { // Activate authentication option PrepareAuthenticationTestMD5(50, 9, "123456789"); TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); // Prepare the packet. int pkt_len = LEN_PKT_NOMAC; testpkt.exten[0] = htonl(50); int mac_len = make_mac((char*)&testpkt, pkt_len, MAX_MD5_LEN, key_ptr, (char*)&testpkt.exten[1]); pkt_len += 4 + mac_len; // Now, alter the MAC so it becomes invalid. testpkt.exten[1] += 1; TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL, process_pkt(&testpkt, &testsock, pkt_len, MODE_SERVER, &testspkt, "UnitTest")); }
static size_t file_size(char const * fname) { struct stat stbf; if (stat(fname, &stbf) != 0) { fswarn("stat", fname); return 0; } if (! S_ISREG(stbf.st_mode)) { fswarn("regular file check", fname); return 0; } if ((outfile_time < stbf.st_mtime) && ENABLED_OPT(SOURCE_TIME)) outfile_time = stbf.st_mtime; if (maxfile_time < stbf.st_mtime) maxfile_time = stbf.st_mtime; return stbf.st_size; }
void offset_calculation ( struct pkt *rpkt, int rpktl, struct timeval *tv_dst, double *offset, double *precision, double *root_dispersion ) { l_fp p_rec, p_xmt, p_ref, p_org, tmp, dst; u_fp p_rdly, p_rdsp; double t21, t34, delta; /* Convert timestamps from network to host byte order */ p_rdly = NTOHS_FP(rpkt->rootdelay); p_rdsp = NTOHS_FP(rpkt->rootdisp); NTOHL_FP(&rpkt->reftime, &p_ref); NTOHL_FP(&rpkt->org, &p_org); NTOHL_FP(&rpkt->rec, &p_rec); NTOHL_FP(&rpkt->xmt, &p_xmt); *precision = LOGTOD(rpkt->precision); #ifdef DEBUG printf("sntp precision: %f\n", *precision); #endif /* DEBUG */ *root_dispersion = FPTOD(p_rdsp); #ifdef DEBUG printf("sntp rootdelay: %f\n", FPTOD(p_rdly)); printf("sntp rootdisp: %f\n", *root_dispersion); pkt_output(rpkt, rpktl, stdout); printf("sntp offset_calculation: rpkt->reftime:\n"); l_fp_output(&(rpkt->reftime), stdout); printf("sntp offset_calculation: rpkt->org:\n"); l_fp_output(&(rpkt->org), stdout); printf("sntp offset_calculation: rpkt->rec:\n"); l_fp_output(&(rpkt->rec), stdout); printf("sntp offset_calculation: rpkt->rec:\n"); l_fp_output_bin(&(rpkt->rec), stdout); printf("sntp offset_calculation: rpkt->rec:\n"); l_fp_output_dec(&(rpkt->rec), stdout); printf("sntp offset_calculation: rpkt->xmt:\n"); l_fp_output(&(rpkt->xmt), stdout); #endif /* Compute offset etc. */ tmp = p_rec; L_SUB(&tmp, &p_org); LFPTOD(&tmp, t21); TVTOTS(tv_dst, &dst); dst.l_ui += JAN_1970; tmp = p_xmt; L_SUB(&tmp, &dst); LFPTOD(&tmp, t34); *offset = (t21 + t34) / 2.; delta = t21 - t34; if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp offset_calculation:\tt21: %.6f\t\t t34: %.6f\n\t\tdelta: %.6f\t offset: %.6f\n", t21, t34, delta, *offset); }
/* 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; }
int process_pkt ( struct pkt *rpkt, sockaddr_u *sas, int pkt_len, int mode, struct pkt *spkt, const char * func_name ) { unsigned int key_id = 0; struct key *pkt_key = NULL; int is_authentic = 0; unsigned int exten_words, exten_words_used = 0; int mac_size; /* * Parse the extension field if present. We figure out whether * an extension field is present by measuring the MAC size. If * the number of words following the packet header is 0, no MAC * is present and the packet is not authenticated. If 1, the * packet is a crypto-NAK; if 3, the packet is authenticated * with DES; if 5, the packet is authenticated with MD5; if 6, * the packet is authenticated with SHA. If 2 or 4, the packet * is a runt and discarded forthwith. If greater than 6, an * extension field is present, so we subtract the length of the * field and go around again. */ if (pkt_len < (int)LEN_PKT_NOMAC || (pkt_len & 3) != 0) { unusable: if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp %s: Funny packet length: %i. Discarding package.\n", func_name, pkt_len); return PACKET_UNUSEABLE; } /* skip past the extensions, if any */ exten_words = ((unsigned)pkt_len - LEN_PKT_NOMAC) >> 2; while (exten_words > 6) { unsigned int exten_len; exten_len = ntohl(rpkt->exten[exten_words_used]) & 0xffff; exten_len = (exten_len + 7) >> 2; /* convert to words, add 1 */ if (exten_len > exten_words || exten_len < 5) goto unusable; exten_words -= exten_len; exten_words_used += exten_len; } switch (exten_words) { case 1: key_id = ntohl(rpkt->exten[exten_words_used]); printf("Crypto NAK = 0x%08x\n", key_id); break; case 5: case 6: /* Look for the key used by the server in the specified keyfile * and if existent, fetch it or else leave the pointer untouched */ key_id = ntohl(rpkt->exten[exten_words_used]); get_key(key_id, &pkt_key); if (!pkt_key) { printf("unrecognized key ID = 0x%08x\n", key_id); break; } /* Seems like we've got a key with matching keyid */ /* Generate a md5sum of the packet with the key from our keyfile * and compare those md5sums */ mac_size = exten_words << 2; if (!auth_md5((char *)rpkt, pkt_len - mac_size, mac_size - 4, pkt_key)) { break; } /* Yay! Things worked out! */ if (ENABLED_OPT(NORMALVERBOSE)) { char *hostname = ss_to_str(sas); printf("sntp %s: packet received from %s successfully authenticated using key id %i.\n", func_name, hostname, key_id); free(hostname); } is_authentic = 1; break; case 0: break; default: goto unusable; break; } if (!is_authentic) { if (ENABLED_OPT(AUTHENTICATION)) { /* We want a authenticated packet */ if (ENABLED_OPT(NORMALVERBOSE)) { char *hostname = ss_to_str(sas); printf("sntp %s: packet received from %s is not authentic. Will discard it.\n", func_name, hostname); free(hostname); } return SERVER_AUTH_FAIL; } /* We don't know if the user wanted authentication so let's * use it anyways */ if (ENABLED_OPT(NORMALVERBOSE)) { char *hostname = ss_to_str(sas); printf("sntp %s: packet received from %s is not authentic. Authentication not enforced.\n", func_name, hostname); free(hostname); } } /* Check for server's ntp version */ if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION || PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) { if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp %s: Packet shows wrong version (%i)\n", func_name, PKT_VERSION(rpkt->li_vn_mode)); return SERVER_UNUSEABLE; } /* We want a server to sync with */ if (PKT_MODE(rpkt->li_vn_mode) != mode && PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE) { if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp %s: mode %d stratum %i\n", func_name, PKT_MODE(rpkt->li_vn_mode), rpkt->stratum); return SERVER_UNUSEABLE; } /* Stratum is unspecified (0) check what's going on */ if (STRATUM_PKT_UNSPEC == rpkt->stratum) { char *ref_char; if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp %s: Stratum unspecified, going to check for KOD (stratum: %i)\n", func_name, rpkt->stratum); ref_char = (char *) &rpkt->refid; if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp %s: Packet refid: %c%c%c%c\n", func_name, ref_char[0], ref_char[1], ref_char[2], ref_char[3]); /* If it's a KOD packet we'll just use the KOD information */ if (ref_char[0] != 'X') { if (strncmp(ref_char, "DENY", 4) == 0) return KOD_DEMOBILIZE; if (strncmp(ref_char, "RSTR", 4) == 0) return KOD_DEMOBILIZE; if (strncmp(ref_char, "RATE", 4) == 0) return KOD_RATE; /* There are other interesting kiss codes which might be interesting for authentication */ } } /* If the server is not synced it's not really useable for us */ if (LEAP_NOTINSYNC == PKT_LEAP(rpkt->li_vn_mode)) { if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp %s: Server not in sync, skipping this server\n", func_name); return SERVER_UNUSEABLE; } /* * Decode the org timestamp and make sure we're getting a response * to our last request, but only if we're not in broadcast mode. */ #ifdef DEBUG printf("rpkt->org:\n"); l_fp_output(&rpkt->org, stdout); printf("spkt->xmt:\n"); l_fp_output(&spkt->xmt, stdout); #endif if (mode != MODE_BROADCAST && !L_ISEQU(&rpkt->org, &spkt->xmt)) { if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp process_pkt: pkt.org and peer.xmt differ\n"); return PACKET_UNUSEABLE; } return pkt_len; }
/* * The actual main function. */ int sntp_main ( int argc, char **argv ) { register int c; struct kod_entry *reason = NULL; int optct; /* boolean, u_int quiets gcc4 signed overflow warning */ u_int sync_data_suc; struct addrinfo **bcastaddr = NULL; struct addrinfo **resh = NULL; struct addrinfo *ai; int resc; int kodc; int ow_ret; int bcast = 0; char *hostname; optct = optionProcess(&sntpOptions, argc, argv); argc -= optct; argv += optct; /* Initialize logging system */ init_logging(); if (HAVE_OPT(LOGFILE)) open_logfile(OPT_ARG(LOGFILE)); msyslog(LOG_NOTICE, "Started sntp"); /* IPv6 available? */ if (isc_net_probeipv6() != ISC_R_SUCCESS) { ai_fam_pref = AF_INET; #ifdef DEBUG printf("No ipv6 support available, forcing ipv4\n"); #endif } else { /* Check for options -4 and -6 */ if (HAVE_OPT(IPV4)) ai_fam_pref = AF_INET; else if (HAVE_OPT(IPV6)) ai_fam_pref = AF_INET6; } /* Parse config file if declared TODO */ /* * If there's a specified KOD file init KOD system. If not use * default file. For embedded systems with no writable * filesystem, -K /dev/null can be used to disable KoD storage. */ if (HAVE_OPT(KOD)) kod_init_kod_db(OPT_ARG(KOD)); else kod_init_kod_db("/var/db/ntp-kod"); if (HAVE_OPT(KEYFILE)) auth_init(OPT_ARG(KEYFILE), &keys); #ifdef EXERCISE_KOD_DB add_entry("192.168.169.170", "DENY"); add_entry("192.168.169.171", "DENY"); add_entry("192.168.169.172", "DENY"); add_entry("192.168.169.173", "DENY"); add_entry("192.168.169.174", "DENY"); delete_entry("192.168.169.174", "DENY"); delete_entry("192.168.169.172", "DENY"); delete_entry("192.168.169.170", "DENY"); if ((kodc = search_entry("192.168.169.173", &reason)) == 0) printf("entry for 192.168.169.173 not found but should have been!\n"); else free(reason); #endif /* Considering employing a variable that prevents functions of doing anything until * everything is initialized properly */ resc = resolve_hosts((void *)argv, argc, &resh, ai_fam_pref); if (resc < 1) { printf("Unable to resolve hostname(s)\n"); return -1; } bcast = ENABLED_OPT(BROADCAST); if (bcast) { const char * myargv[2]; myargv[0] = OPT_ARG(BROADCAST); myargv[1] = NULL; bcast = resolve_hosts(myargv, 1, &bcastaddr, ai_fam_pref); } /* Select a certain ntp server according to simple criteria? For now * let's just pay attention to previous KoDs. */ sync_data_suc = FALSE; for (c = 0; c < resc && !sync_data_suc; c++) { ai = resh[c]; do { hostname = addrinfo_to_str(ai); if ((kodc = search_entry(hostname, &reason)) == 0) { if (is_reachable(ai)) { ow_ret = on_wire(ai, bcast ? bcastaddr[0] : NULL); if (0 == ow_ret) sync_data_suc = TRUE; } } else { printf("%d prior KoD%s for %s, skipping.\n", kodc, (kodc > 1) ? "s" : "", hostname); free(reason); } free(hostname); ai = ai->ai_next; } while (NULL != ai); freeaddrinfo(resh[c]); } free(resh); if (!sync_data_suc) return 1; return 0; }
/* Receive data from broadcast. Couldn't finish that. Need to do some digging * here, especially for protocol independence and IPv6 multicast */ int recv_bcst_data ( SOCKET rsock, char *rdata, int rdata_len, sockaddr_u *sas, sockaddr_u *ras ) { char *buf; int btrue = 1; int recv_bytes = 0; int rdy_socks; GETSOCKNAME_SOCKLEN_TYPE ss_len; struct timeval timeout_tv; fd_set bcst_fd; #ifdef MCAST struct ip_mreq mdevadr; TYPEOF_IP_MULTICAST_LOOP mtrue = 1; #endif #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT struct ipv6_mreq mdevadr6; #endif setsockopt(rsock, SOL_SOCKET, SO_REUSEADDR, &btrue, sizeof(btrue)); if (IS_IPV4(sas)) { if (bind(rsock, &sas->sa, SOCKLEN(sas)) < 0) { if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recv_bcst_data: Couldn't bind() address %s:%d.\n", stoa(sas), SRCPORT(sas)); } #ifdef MCAST if (setsockopt(rsock, IPPROTO_IP, IP_MULTICAST_LOOP, &mtrue, sizeof(mtrue)) < 0) { /* some error message regarding setting up multicast loop */ return BROADCAST_FAILED; } mdevadr.imr_multiaddr.s_addr = NSRCADR(sas); mdevadr.imr_interface.s_addr = htonl(INADDR_ANY); if (mdevadr.imr_multiaddr.s_addr == ~(unsigned)0) { if (ENABLED_OPT(NORMALVERBOSE)) { printf("sntp recv_bcst_data: %s:%d is not a broad-/multicast address, aborting...\n", stoa(sas), SRCPORT(sas)); } return BROADCAST_FAILED; } if (setsockopt(rsock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mdevadr, sizeof(mdevadr)) < 0) { if (ENABLED_OPT(NORMALVERBOSE)) { buf = ss_to_str(sas); printf("sntp recv_bcst_data: Couldn't add IP membership for %s\n", buf); free(buf); } } #endif /* MCAST */ } #ifdef ISC_PLATFORM_HAVEIPV6 else if (IS_IPV6(sas)) { if (bind(rsock, &sas->sa, SOCKLEN(sas)) < 0) { if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recv_bcst_data: Couldn't bind() address.\n"); } #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT if (setsockopt(rsock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &btrue, sizeof (btrue)) < 0) { /* some error message regarding setting up multicast loop */ return BROADCAST_FAILED; } memset(&mdevadr6, 0, sizeof(mdevadr6)); mdevadr6.ipv6mr_multiaddr = SOCK_ADDR6(sas); if (!IN6_IS_ADDR_MULTICAST(&mdevadr6.ipv6mr_multiaddr)) { if (ENABLED_OPT(NORMALVERBOSE)) { buf = ss_to_str(sas); printf("sntp recv_bcst_data: %s is not a broad-/multicast address, aborting...\n", buf); free(buf); } return BROADCAST_FAILED; } if (setsockopt(rsock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mdevadr6, sizeof(mdevadr6)) < 0) { if (ENABLED_OPT(NORMALVERBOSE)) { buf = ss_to_str(sas); printf("sntp recv_bcst_data: Couldn't join group for %s\n", buf); free(buf); } } #endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */ } #endif /* ISC_PLATFORM_HAVEIPV6 */ FD_ZERO(&bcst_fd); FD_SET(rsock, &bcst_fd); if (ENABLED_OPT(TIMEOUT)) timeout_tv.tv_sec = (int) atol(OPT_ARG(TIMEOUT)); else timeout_tv.tv_sec = 68; /* ntpd broadcasts every 64s */ timeout_tv.tv_usec = 0; rdy_socks = select(rsock + 1, &bcst_fd, 0, 0, &timeout_tv); switch (rdy_socks) { case -1: if (ENABLED_OPT(NORMALVERBOSE)) perror("sntp recv_bcst_data: select()"); return BROADCAST_FAILED; break; case 0: if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recv_bcst_data: select() reached timeout (%u sec), aborting.\n", (unsigned)timeout_tv.tv_sec); return BROADCAST_FAILED; break; default: ss_len = sizeof(*ras); recv_bytes = recvfrom(rsock, rdata, rdata_len, 0, &ras->sa, &ss_len); break; } if (recv_bytes == -1) { if (ENABLED_OPT(NORMALVERBOSE)) perror("sntp recv_bcst_data: recvfrom:"); recv_bytes = BROADCAST_FAILED; } #ifdef MCAST if (IS_IPV4(sas)) setsockopt(rsock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &btrue, sizeof(btrue)); #endif #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT if (IS_IPV6(sas)) setsockopt(rsock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &btrue, sizeof(btrue)); #endif return recv_bytes; }