void test_VerifySHA1(void) { #ifdef OPENSSL const char* PKT_DATA = "sometestdata" /* Data */ "\0\0\0\0" /* Key-ID (unused) */ "\xad\x07\xde\x36\x39\xa6\x77\xfa\x5b\xce" /* MAC */ "\x2d\x8a\x7d\x06\x96\xe6\x0c\xbc\xed\xe1"; const int PKT_LEN = 12; struct key sha1; sha1.next = NULL; sha1.key_id = 0; sha1.key_len = 7; memcpy(&sha1.key_seq, "sha1key", sha1.key_len); memcpy(&sha1.type, "SHA1", 5); TEST_ASSERT_TRUE(auth_md5(PKT_DATA, PKT_LEN, SHA1_LENGTH, &sha1)); #else TEST_IGNORE_MESSAGE("OpenSSL not found, skipping..."); #endif /* OPENSSL */ }
void test_VerifyCorrectMD5(void) { const char* PKT_DATA = "sometestdata" // Data "\0\0\0\0" // Key-ID (unused) "\xc7\x58\x99\xdd\x99\x32\x0f\x71" // MAC "\x2b\x7b\xfe\x4f\xa2\x32\xcf\xac"; const int PKT_LEN = 12; struct key md5; md5.next = NULL; md5.key_id = 0; md5.key_len = 6; memcpy(&md5.key_seq, "md5key", md5.key_len); memcpy(&md5.type, "MD5", 4); TEST_ASSERT_TRUE(auth_md5((char*)PKT_DATA, PKT_LEN, MD5_LENGTH, &md5)); }
void test_VerifyFailure(void) { /* We use a copy of the MD5 verification code, but modify * the last bit to make sure verification fails. */ const char* PKT_DATA = "sometestdata" // Data "\0\0\0\0" // Key-ID (unused) "\xc7\x58\x99\xdd\x99\x32\x0f\x71" // MAC "\x2b\x7b\xfe\x4f\xa2\x32\xcf\x00"; // Last byte is wrong! const int PKT_LEN = 12; struct key md5; md5.next = NULL; md5.key_id = 0; md5.key_len = 6; memcpy(&md5.key_seq, "md5key", md5.key_len); memcpy(&md5.type, "MD5", 4); TEST_ASSERT_FALSE(auth_md5((char*)PKT_DATA, PKT_LEN, MD5_LENGTH, &md5)); }
void test_VerifyCorrectMD5(void) { const char* PKT_DATA = "sometestdata" /* Data */ "\0\0\0\0" /* Key-ID (unused) */ "\xc7\x58\x99\xdd\x99\x32\x0f\x71" /* MAC */ "\x2b\x7b\xfe\x4f\xa2\x32\xcf\xac"; const int PKT_LEN = 12; struct key md5; md5.next = NULL; md5.key_id = 0; md5.key_len = 6; memcpy(&md5.key_seq, "md5key", md5.key_len); strlcpy(md5.typen, "MD5", sizeof(md5.typen)); md5.typei = keytype_from_text(md5.typen, NULL); TEST_ASSERT_TRUE(auth_md5(PKT_DATA, PKT_LEN, MD5_LENGTH, &md5)); }
void test_VerifyFailure(void) { /* We use a copy of the MD5 verification code, but modify the * last bit to make sure verification fails. */ const char* PKT_DATA = "sometestdata" /* Data */ "\0\0\0\0" /* Key-ID (unused) */ "\xc7\x58\x99\xdd\x99\x32\x0f\x71" /* MAC */ "\x2b\x7b\xfe\x4f\xa2\x32\xcf\x00"; /* Last byte is wrong! */ const int PKT_LEN = 12; struct key md5; md5.next = NULL; md5.key_id = 0; md5.key_len = 6; memcpy(&md5.key_seq, "md5key", md5.key_len); strlcpy(md5.typen, "MD5", sizeof(md5.typen)); md5.typei = keytype_from_text(md5.typen, NULL); TEST_ASSERT_FALSE(auth_md5(PKT_DATA, PKT_LEN, MD5_LENGTH, &md5)); }
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; }
/* ** 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 process_pkt ( struct pkt *rpkt, sockaddr_u *sender, int pkt_len, int mode, struct pkt *spkt, const char * func_name ) { u_int key_id; struct key * pkt_key; int is_authentic; int mac_size; u_int exten_len; u_int32 * exten_end; u_int32 * packet_end; l_fp sent_xmt; l_fp resp_org; // key_id = 0; pkt_key = NULL; is_authentic = (HAVE_OPT(AUTHENTICATION)) ? 0 : -1; /* * 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) { msyslog(LOG_ERR, "%s: Incredible packet length: %d. Discarding.", func_name, pkt_len); return PACKET_UNUSEABLE; } /* HMS: the following needs a bit of work */ /* Note: pkt_len must be a multiple of 4 at this point! */ packet_end = (void*)((char*)rpkt + pkt_len); exten_end = skip_efields(rpkt->exten, packet_end); if (NULL == exten_end) { msyslog(LOG_ERR, "%s: Missing extension field. Discarding.", func_name); return PACKET_UNUSEABLE; } /* get size of MAC in cells; can be zero */ exten_len = (u_int)(packet_end - exten_end); /* deduce action required from remaining length */ switch (exten_len) { case 0: /* no Legacy MAC */ break; case 1: /* crypto NAK */ /* Only if the keyID is 0 and there were no EFs */ key_id = ntohl(*exten_end); printf("Crypto NAK = 0x%08x from %s\n", key_id, stoa(sender)); break; case 3: /* key ID + 3DES MAC -- unsupported! */ msyslog(LOG_ERR, "%s: Key ID + 3DES MAC is unsupported. Discarding.", func_name); return PACKET_UNUSEABLE; case 5: /* key ID + MD5 MAC */ case 6: /* key ID + SHA MAC */ /* ** 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(*exten_end); 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_len << 2; if (!auth_md5(rpkt, pkt_len - mac_size, mac_size - 4, pkt_key)) { is_authentic = FALSE; break; } /* Yay! Things worked out! */ is_authentic = TRUE; TRACE(1, ("sntp %s: packet from %s authenticated using key id %d.\n", func_name, stoa(sender), key_id)); break; default: msyslog(LOG_ERR, "%s: Unexpected extension length: %d. Discarding.", func_name, exten_len); return PACKET_UNUSEABLE; } switch (is_authentic) { case -1: /* unknown */ break; case 0: /* not authentic */ return SERVER_AUTH_FAIL; break; case 1: /* authentic */ break; default: /* error */ break; } /* Check for server's ntp version */ if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION || PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) { msyslog(LOG_ERR, "%s: Packet shows wrong version (%d)", 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) { msyslog(LOG_ERR, "%s: mode %d stratum %d", 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; TRACE(1, ("%s: Stratum unspecified, going to check for KOD (stratum: %d)\n", func_name, rpkt->stratum)); ref_char = (char *) &rpkt->refid; TRACE(1, ("%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)) { msyslog(LOG_ERR, "%s: %s not in sync, skipping this server", func_name, stoa(sender)); 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. */ if (MODE_BROADCAST == mode) return pkt_len; if (!L_ISEQU(&rpkt->org, &spkt->xmt)) { NTOHL_FP(&rpkt->org, &resp_org); NTOHL_FP(&spkt->xmt, &sent_xmt); msyslog(LOG_ERR, "%s response org expected to match sent xmt", stoa(sender)); msyslog(LOG_ERR, "resp org: %s", prettydate(&resp_org)); msyslog(LOG_ERR, "sent xmt: %s", prettydate(&sent_xmt)); return PACKET_UNUSEABLE; } return pkt_len; }
/* 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, struct pkt *spkt ) { sockaddr_u sender; char *rdata /* , done */; register int a; int has_mac, is_authentic, pkt_len, orig_pkt_len; /* Much space, just to be sure */ rdata = emalloc(sizeof(char) * 256); pkt_len = recvdata(rsock, &sender, rdata, 256); #if 0 /* done uninitialized */ if (!done) { /* Do something about it, first check for a maximum length of ntp packets, * probably that's something we can avoid */ } #endif if (pkt_len < 0) { if (ENABLED_OPT(NORMALVERBOSE)) { printf("sntp recvpkt failed: %d.\n", pkt_len); } free(rdata); return pkt_len; } /* Some checks to see if that packet is intended for us */ /* No MAC, no authentication */ if (LEN_PKT_NOMAC == pkt_len) has_mac = 0; /* If there's more than just the NTP packet it should be a MAC */ else if (pkt_len > LEN_PKT_NOMAC) has_mac = pkt_len - LEN_PKT_NOMAC; else { if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recvpkt: Funny packet length: %i. Discarding package.\n", pkt_len); free(rdata); return PACKET_UNUSEABLE; } /* Packet too big */ if (pkt_len > LEN_PKT_MAC) { if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recvpkt: Received packet is too big (%i bytes), trying again to get a useable packet\n", pkt_len); free(rdata); return PACKET_UNUSEABLE; } orig_pkt_len = pkt_len; pkt_len = min(pkt_len, sizeof(struct pkt)); for (a = 0; a < pkt_len; a++) /* FIXME! */ if (a < orig_pkt_len) ((char *) rpkt)[a] = rdata[a]; else ((char *) rpkt)[a] = 0; free(rdata); rdata = NULL; /* MAC could be useable for us */ if (has_mac) { /* Two more things that the MAC must conform to */ if(has_mac > MAX_MAC_LEN || has_mac % 4 != 0) { is_authentic = 0; /* Or should we discard this packet? */ } else { if (MAX_MAC_LEN == has_mac) { struct key *pkt_key = NULL; /* * Look for the key used by the server in the specified keyfile * and if existent, fetch it or else leave the pointer untouched */ get_key(rpkt->mac[0], &pkt_key); /* Seems like we've got a key with matching keyid */ if (pkt_key != NULL) { /* * Generate a md5sum of the packet with the key from our keyfile * and compare those md5sums */ if (!auth_md5((char *) rpkt, has_mac, pkt_key)) { if (ENABLED_OPT(AUTHENTICATION)) { /* We want a authenticated packet */ if (ENABLED_OPT(NORMALVERBOSE)) { char *hostname = ss_to_str(&sender); printf("sntp recvpkt: Broadcast packet received from %s is not authentic. Will discard this packet.\n", hostname); free(hostname); } return SERVER_AUTH_FAIL; } else { /* * We don't know if the user wanted authentication so let's * use it anyways */ if (ENABLED_OPT(NORMALVERBOSE)) { char *hostname = ss_to_str(&sender); printf("sntp recvpkt: Broadcast packet received from %s is not authentic. Authentication not enforced.\n", hostname); free(hostname); } is_authentic = 0; } } else { /* Yay! Things worked out! */ if (ENABLED_OPT(NORMALVERBOSE)) { char *hostname = ss_to_str(&sender); printf("sntp recvpkt: Broadcast packet received from %s successfully authenticated using key id %i.\n", hostname, rpkt->mac[0]); free(hostname); } is_authentic = 1; } } } } } /* 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 recvpkt: Packet got wrong version (%i)\n", PKT_VERSION(rpkt->li_vn_mode)); return SERVER_UNUSEABLE; } /* We want a server to sync with */ if (PKT_MODE(rpkt->li_vn_mode) != MODE_SERVER && PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE) { if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recvpkt: mode %d stratum %i\n", 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 recvpkt: Stratum unspecified, going to check for KOD (stratum: %i)\n", rpkt->stratum); ref_char = (char *) &rpkt->refid; if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recvpkt: Packet refid: %c%c%c%c\n", 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)) return KOD_DEMOBILIZE; if (!strncmp(ref_char, "RSTR", 4)) return KOD_DEMOBILIZE; if (!strncmp(ref_char, "RATE", 4)) 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 recvpkt: Server not in sync, skipping this server\n"); return SERVER_UNUSEABLE; } /* * Decode the org timestamp and make sure we're getting a response * to our last request. */ #ifdef DEBUG printf("rpkt->org:\n"); l_fp_output(&rpkt->org, stdout); printf("spkt->xmt:\n"); l_fp_output(&spkt->xmt, stdout); #endif if (!L_ISEQU(&rpkt->org, &spkt->xmt)) { if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recvpkt: pkt.org and peer.xmt differ\n"); return PACKET_UNUSEABLE; } return pkt_len; }
int recv_bcst_pkt ( SOCKET rsock, struct pkt *rpkt, sockaddr_u *sas ) { sockaddr_u sender; register int a; int is_authentic, has_mac = 0, orig_pkt_len; char *rdata = emalloc(sizeof(char) * 256); int pkt_len = recv_bcst_data(rsock, rdata, 256, sas, &sender); if (pkt_len < 0) { free(rdata); return BROADCAST_FAILED; } /* No MAC, no authentication */ if (LEN_PKT_NOMAC == pkt_len) has_mac = 0; /* If there's more than just the NTP packet it should be a MAC */ else if(pkt_len > LEN_PKT_NOMAC) has_mac = pkt_len - LEN_PKT_NOMAC; else if(ENABLED_OPT(NORMALVERBOSE)) { printf("sntp recv_bcst_pkt: Funny packet length: %i. Discarding package.\n", pkt_len); free(rdata); return PACKET_UNUSEABLE; } /* Packet too big */ if(pkt_len > LEN_PKT_NOMAC + MAX_MAC_LEN) { if(ENABLED_OPT(NORMALVERBOSE)) printf("sntp recv_bcst_pkt: Received packet is too big (%i bytes), trying again to get a useFable packet\n", pkt_len); free(rdata); return PACKET_UNUSEABLE; } orig_pkt_len = pkt_len; pkt_len = min(pkt_len, sizeof(struct pkt)); /* Let's copy the received data to the packet structure */ for (a = 0; a < pkt_len; a++) if (a < orig_pkt_len) ((char *)rpkt)[a] = rdata[a]; else ((char *)rpkt)[a] = 0; free(rdata); /* MAC could be useable for us */ if (has_mac) { /* Two more things that the MAC must conform to */ if (has_mac > MAX_MAC_LEN || has_mac % 4 != 0) { is_authentic = 0; /* Or should we discard this packet? */ } else { if (MAX_MAC_LEN == has_mac) { struct key *pkt_key = NULL; /* Look for the key used by the server in the specified keyfile * and if existent, fetch it or else leave the pointer untouched */ get_key(rpkt->mac[0], &pkt_key); /* Seems like we've got a key with matching keyid */ if (pkt_key != NULL) { /* Generate a md5sum of the packet with the key from our keyfile * and compare those md5sums */ if (!auth_md5((char *) rpkt, has_mac, pkt_key)) { if (ENABLED_OPT(AUTHENTICATION)) { /* We want a authenticated packet */ if (ENABLED_OPT(NORMALVERBOSE)) { char *hostname = ss_to_str(sas); printf("sntp recv_bcst_pkt: Broadcast packet received from %s is not authentic. Will discard this packet.\n", hostname); free(hostname); } return SERVER_AUTH_FAIL; } else { /* 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 recv_bcst_pkt: Broadcast packet received from %s is not authentic. Authentication not enforced.\n", hostname); free(hostname); } is_authentic = 0; } } else { /* Yay! Things worked out! */ if (ENABLED_OPT(NORMALVERBOSE)) { char *hostname = ss_to_str(sas); printf("sntp recv_bcst_pkt: Broadcast packet received from %s successfully authenticated using key id %i.\n", hostname, rpkt->mac[0]); free(hostname); } is_authentic = 1; } } } } } /* 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 recv_bcst_pkt: Packet shows wrong version (%i)\n", PKT_VERSION(rpkt->li_vn_mode)); return SERVER_UNUSEABLE; } /* We want a server to sync with */ if (PKT_MODE(rpkt->li_vn_mode) != MODE_BROADCAST && PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE) { if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recv_bcst_pkt: mode %d stratum %i\n", PKT_MODE(rpkt->li_vn_mode), rpkt->stratum); return SERVER_UNUSEABLE; } if (STRATUM_PKT_UNSPEC == rpkt->stratum) { char *ref_char; if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recv_bcst_pkt: Stratum unspecified, going to check for KOD (stratum: %i)\n", rpkt->stratum); ref_char = (char *) &rpkt->refid; /* If it's a KOD packet we'll just use the KOD information */ if (ref_char[0] != 'X') { if (strncmp(ref_char, "DENY", 4)) return KOD_DEMOBILIZE; if (strncmp(ref_char, "RSTR", 4)) return KOD_DEMOBILIZE; if (strncmp(ref_char, "RATE", 4)) 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("recv_bcst_pkt: Server not in sync, skipping this server\n"); return SERVER_UNUSEABLE; } return pkt_len; }