Ejemplo n.º 1
0
int 
recv_bcst_pkt (
	SOCKET rsock,
	struct pkt *rpkt,
	unsigned int rsize,
	sockaddr_u *sas
	)
{
	sockaddr_u sender;
	int pkt_len = recv_bcst_data(rsock, (char *)rpkt, rsize, sas, &sender);
	if (pkt_len < 0) {
		return BROADCAST_FAILED;
	}
	pkt_len = process_pkt(rpkt, sas, pkt_len, MODE_BROADCAST, NULL, "recv_bcst_pkt");
	return pkt_len;
}
Ejemplo n.º 2
0
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;
}