⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ntp_proto.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * than 5, an extension field is present, so we subtract the	 * length of the field and go around again.	 */	authlen = LEN_PKT_NOMAC;	has_mac = rbufp->recv_length - authlen;	while (has_mac > 0) {		int temp;		if (has_mac % 4 != 0 || has_mac < 0) {			sys_badlength++;			return;			/* bad MAC length */		}		if (has_mac == 1 * 4 || has_mac == 3 * 4 || has_mac ==		    MAX_MAC_LEN) {			skeyid = ntohl(((u_int32 *)pkt)[authlen / 4]);			break;		} else if (has_mac > MAX_MAC_LEN) {			temp = ntohl(((u_int32 *)pkt)[authlen / 4]) &			    0xffff;			if (temp < 4 || temp > NTP_MAXEXTEN || temp % 4			    != 0) {				sys_badlength++;				return;		/* bad MAC length */			}			authlen += temp;			has_mac -= temp;		} else {			sys_badlength++;			return;			/* bad MAC length */		}	}#ifdef OPENSSL	pkeyid = tkeyid = 0;#endif /* OPENSSL */	/*	 * We have tossed out as many buggy packets as possible early in	 * the game to reduce the exposure to a clogging attack. Now we	 * have to burn some cycles to find the association and	 * authenticate the packet if required. Note that we burn only	 * MD5 cycles, again to reduce exposure. There may be no	 * matching association and that's okay.	 *	 * More on the autokey mambo. Normally the local interface is	 * found when the association was mobilized with respect to a	 * designated remote address. We assume packets arriving from	 * the remote address arrive via this interface and the local	 * address used to construct the autokey is the unicast address	 * of the interface. However, if the sender is a broadcaster,	 * the interface broadcast address is used instead.	 & Notwithstanding this technobabble, if the sender is a	 * multicaster, the broadcast address is null, so we use the	 * unicast address anyway. Don't ask.	 */	peer = findpeer(&rbufp->recv_srcadr, rbufp->dstadr,  hismode,	    &retcode);	dstadr_sin = &rbufp->dstadr->sin;	NTOHL_FP(&pkt->org, &p_org);	NTOHL_FP(&pkt->rec, &p_rec);	NTOHL_FP(&pkt->xmt, &p_xmt);	/*	 * Authentication is conditioned by three switches:	 *	 * NOPEER  (RES_NOPEER) do not mobilize an association unless	 *         authenticated	 * NOTRUST (RES_DONTTRUST) do not allow access unless	 *         authenticated (implies NOPEER)	 * enable  (sys_authenticate) master NOPEER switch, by default	 *         on	 *	 * The NOPEER and NOTRUST can be specified on a per-client basis	 * using the restrict command. The enable switch if on implies	 * NOPEER for all clients. There are four outcomes:	 *	 * NONE    The packet has no MAC.	 * OK      the packet has a MAC and authentication succeeds	 * ERROR   the packet has a MAC and authentication fails	 * CRYPTO  crypto-NAK. The MAC has four octets only.	 *	 * Note: The AUTH(x, y) macro is used to filter outcomes. If x	 * is zero, acceptable outcomes of y are NONE and OK. If x is	 * one, the only acceptable outcome of y is OK.	 */	if (has_mac == 0) {		is_authentic = AUTH_NONE; /* not required */#ifdef DEBUG		if (debug)			printf("receive: at %ld %s<-%s mode %d code %d auth %d\n",			    current_time, stoa(dstadr_sin),			    stoa(&rbufp->recv_srcadr), hismode, retcode,			    is_authentic);#endif	} else if (has_mac == 4) {			is_authentic = AUTH_CRYPTO; /* crypto-NAK */#ifdef DEBUG		if (debug)			printf(			    "receive: at %ld %s<-%s mode %d code %d keyid %08x len %d mac %d auth %d\n",			    current_time, stoa(dstadr_sin),			    stoa(&rbufp->recv_srcadr), hismode, retcode,			    skeyid, authlen, has_mac, is_authentic);#endif	} else {#ifdef OPENSSL		/*		 * For autokey modes, generate the session key		 * and install in the key cache. Use the socket		 * broadcast or unicast address as appropriate.		 */		if (skeyid > NTP_MAXKEY) {					/*			 * More on the autokey dance (AKD). A cookie is			 * constructed from public and private values.			 * For broadcast packets, the cookie is public			 * (zero). For packets that match no			 * association, the cookie is hashed from the			 * addresses and private value. For server			 * packets, the cookie was previously obtained			 * from the server. For symmetric modes, the			 * cookie was previously constructed using an			 * agreement protocol; however, should PKI be			 * unavailable, we construct a fake agreement as			 * the EXOR of the peer and host cookies.			 *			 * hismode	ephemeral	persistent			 * =======================================			 * active	0		cookie#			 * passive	0%		cookie#			 * client	sys cookie	0%			 * server	0%		sys cookie			 * broadcast	0		0			 *			 * # if unsync, 0			 * % can't happen			 */			if (hismode == MODE_BROADCAST) {				/*				 * For broadcaster, use the interface				 * broadcast address when available;				 * otherwise, use the unicast address				 * found when the association was				 * mobilized. However, if this is from				 * the wildcard interface, game over.				 */				if (crypto_flags && rbufp->dstadr ==				    any_interface) {					sys_restricted++;					return;	     /* no wildcard */				}				pkeyid = 0;				if (!SOCKNUL(&rbufp->dstadr->bcast))					dstadr_sin =					    &rbufp->dstadr->bcast;			} else if (peer == NULL) {				pkeyid = session_key(				    &rbufp->recv_srcadr, dstadr_sin, 0,				    sys_private, 0);			} else {				pkeyid = peer->pcookie;			}			/*			 * The session key includes both the public			 * values and cookie. In case of an extension			 * field, the cookie used for authentication			 * purposes is zero. Note the hash is saved for			 * use later in the autokey mambo.			 */			if (authlen > LEN_PKT_NOMAC && pkeyid != 0) {				session_key(&rbufp->recv_srcadr,				    dstadr_sin, skeyid, 0, 2);				tkeyid = session_key(				    &rbufp->recv_srcadr, dstadr_sin,				    skeyid, pkeyid, 0);			} else {				tkeyid = session_key(				    &rbufp->recv_srcadr, dstadr_sin,				    skeyid, pkeyid, 2);			}		}#endif /* OPENSSL */		/*		 * Compute the cryptosum. Note a clogging attack may		 * succeed in bloating the key cache. If an autokey,		 * purge it immediately, since we won't be needing it		 * again. If the packet is authentic, it can mobilize an		 * association. Note that there is no key zero.		 */		if (!authdecrypt(skeyid, (u_int32 *)pkt, authlen,		    has_mac)) {			is_authentic = AUTH_ERROR;			sys_badauth++;		} else {			is_authentic = AUTH_OK;		}#ifdef OPENSSL		if (skeyid > NTP_MAXKEY)			authtrust(skeyid, 0);#endif /* OPENSSL */#ifdef DEBUG		if (debug)			printf(			    "receive: at %ld %s<-%s mode %d code %d keyid %08x len %d mac %d auth %d\n",			    current_time, stoa(dstadr_sin),			    stoa(&rbufp->recv_srcadr), hismode, retcode,			    skeyid, authlen, has_mac, is_authentic);#endif	}	/*	 * The association matching rules are implemented by a set of	 * routines and an association table. A packet matching an	 * association is processed by the peer process for that	 * association. If there are no errors, an ephemeral association	 * is mobilized: a broadcast packet mobilizes a broadcast client	 * aassociation; a manycast server packet mobilizes a manycast	 * client association; a symmetric active packet mobilizes a	 * symmetric passive association.	 */	switch (retcode) {	/*	 * This is a client mode packet not matching any association. If	 * an ordinary client, simply toss a server mode packet back	 * over the fence. If a manycast client, we have to work a	 * little harder.	 */	case AM_FXMIT:		/*		 * The vanilla case is when this is not a multicast		 * interface. If authentication succeeds, return a		 * server mode packet; if not and the key ID is nonzero,		 * return a crypto-NAK.		 */		if (!(rbufp->dstadr->flags & INT_MCASTOPEN)) {			if (AUTH(restrict_mask & RES_DONTTRUST,			   is_authentic))				fast_xmit(rbufp, MODE_SERVER, skeyid,				    restrict_mask);			else if (is_authentic == AUTH_ERROR)				fast_xmit(rbufp, MODE_SERVER, 0,				    restrict_mask);			return;			/* hooray */		}		/*		 * This must be manycast. Do not respond if not		 * configured as a manycast server.		 */		if (!sys_manycastserver) {			sys_restricted++;			return;			/* not enabled */		}		/*		 * Do not respond if unsynchronized or stratum is below		 * the floor or at or above the ceiling.		 */		if (sys_leap == LEAP_NOTINSYNC || sys_stratum <		    sys_floor || sys_stratum >= sys_ceiling)			return;			/* bad stratum */		/*		 * Do not respond if our stratum is greater than the		 * manycaster or it has already synchronized to us.		 */		if (sys_peer == NULL || hisstratum < sys_stratum ||		    (sys_cohort && hisstratum == sys_stratum) ||		    rbufp->dstadr->addr_refid == pkt->refid)			return;			/* no help */		/*		 * Respond only if authentication succeeds. Don't do a		 * crypto-NAK, as that would not be useful.		 */		if (AUTH(restrict_mask & RES_DONTTRUST, is_authentic))			fast_xmit(rbufp, MODE_SERVER, skeyid,			    restrict_mask);		return;				/* hooray */	/*	 * This is a server mode packet returned in response to a client	 * mode packet sent to a multicast group address. The origin	 * timestamp is a good nonce to reliably associate the reply	 * with what was sent. If there is no match, that's curious and	 * could be an intruder attempting to clog, so we just ignore	 * it.	 *	 * If the packet is authentic and the manycast association is	 * found, we mobilize a client association and copy pertinent	 * variables from the manycast association to the new client	 * association. If not, just ignore the packet.	 *	 * There is an implosion hazard at the manycast client, since	 * the manycast servers send the server packet immediately. If	 * the guy is already here, don't fire up a duplicate.	 */	case AM_MANYCAST:		if (!AUTH(sys_authenticate | (restrict_mask &		    (RES_NOPEER | RES_DONTTRUST)), is_authentic))			return;			/* bad auth */		if ((peer2 = findmanycastpeer(rbufp)) == NULL) {			sys_restricted++;			return;			/* not enabled */		}		if ((peer = newpeer(&rbufp->recv_srcadr,		    rbufp->dstadr, MODE_CLIENT,		    hisversion, NTP_MINDPOLL, NTP_MAXDPOLL,		    FLAG_IBURST | FLAG_PREEMPT, MDF_UCAST | MDF_ACLNT,		    0, skeyid)) == NULL)			return;			/* system error */		/*		 * We don't need these, but it warms the billboards.		 */		peer->ttl = peer2->ttl;		break;	/*	 * This is the first packet received from a broadcast server. If	 * the packet is authentic and we are enabled as broadcast	 * client, mobilize a broadcast client association. We don't	 * kiss any frogs here.	 */	case AM_NEWBCL:		if (!AUTH(sys_authenticate | (restrict_mask &		    (RES_NOPEER | RES_DONTTRUST)), is_authentic))			return;			/* bad auth */		/*		 * Do not respond if unsynchronized or stratum is below		 * the floor or at or above the ceiling.		 */		if (hisleap == LEAP_NOTINSYNC || hisstratum <		    sys_floor || hisstratum >= sys_ceiling)			return;			/* bad stratum */		switch (sys_bclient) {		/*		 * If not enabled, just skedaddle.		 */		case 0:			sys_restricted++;			return;			/* not enabled */		/*		 * Execute the initial volley in order to calibrate the		 * propagation delay and run the Autokey protocol, if		 * enabled.		 */		case 1:			if ((peer = newpeer(&rbufp->recv_srcadr,			    rbufp->dstadr, MODE_CLIENT, hisversion,			    NTP_MINDPOLL, NTP_MAXDPOLL, FLAG_MCAST |			    FLAG_IBURST, MDF_BCLNT, 0, skeyid)) ==			    NULL)				return;		/* system error */#ifdef OPENSSL			if (skeyid > NTP_MAXKEY)				crypto_recv(peer, rbufp);#endif /* OPENSSL */			return;			/* hooray */		/*		 * Do not execute the initial volley.		 */		case 2:#ifdef OPENSSL			/*			 * If a two-way exchange is not possible,			 * neither is Autokey.			 */			if (skeyid > NTP_MAXKEY) {				msyslog(LOG_INFO,				    "receive: autokey requires two-way communication");				return;		/* no autokey */			}#endif /* OPENSSL */			if ((peer = newpeer(&rbufp->recv_srcadr,			    rbufp->dstadr, MODE_BCLIENT, hisversion,			    NTP_MINDPOLL, NTP_MAXDPOLL, 0, MDF_BCLNT, 0,			    skeyid)) == NULL)				return;		/* system error */		}		break;	/*	 * This is the first packet received from a symmetric active	 * peer. If the packet is authentic and the first he sent,	 * mobilize a passive association. If not, kiss the frog.	 */	case AM_NEWPASS:		/*		 * If the inbound packet is correctly authenticated and		 * enabled, a symmetric passive association is		 * mobilized. If not but correctly authenticated, a		 * symmetric active response is sent. If authentication		 * fails, send a crypto-NAK packet. 		 */		if (!AUTH(restrict_mask & RES_DONTTRUST, is_authentic))		    {			if (is_authentic == AUTH_ERROR)				fast_xmit(rbufp, MODE_ACTIVE, 0,				    restrict_mask);			return;			/* bad auth */		}		if (!AUTH(sys_authenticate | (restrict_mask &		    RES_NOPEER), is_authentic)) {			fast_xmit(rbufp, MODE_ACTIVE, skeyid,			    restrict_mask);			return;			/* hooray */		}		/*		 * Do not respond if stratum is below the floor.		 */		if (hisstratum < sys_floor)			return;			/* bad stratum */		if ((peer = newpeer(&rbufp->recv_srcadr,		    rbufp->dstadr, MODE_PASSIVE, hisversion,		    NTP_MINDPOLL, NTP_MAXDPOLL, 0, MDF_UCAST, 0,		    skeyid)) == NULL)			return;			/* system error */		break;	/*	 * Process regular packet. Nothing special.	 */	case AM_PROCPKT:		break;	/*	 * A passive packet matches a passive association. This is	 * usually the result of reconfiguring a client on the fly. As	 * this association might be legitamate and this packet an	 * attempt to deny service, just ignore it.	 */	case AM_ERR:		return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -