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

📄 ntp_crypto.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 5 页
字号:
			ap = (struct autokey *)ep->pkt;			bp->seq = ntohl(ap->seq);			bp->key = ntohl(ap->key);			peer->pkeyid = bp->key;			peer->crypto |= CRYPTO_FLAG_AUTO;			peer->flash &= ~TEST8;			sprintf(statstr,			    "auto seq %d key %x ts %u fs %u", bp->seq,			    bp->key, ntohl(ep->tstamp),			    ntohl(ep->fstamp));			record_crypto_stats(&peer->srcadr, statstr);#ifdef DEBUG			if (debug)				printf("crypto_recv: %s\n", statstr);#endif			break;			/*		 * X509 certificate sign response. Validate the		 * certificate signed by the server and install. Later		 * this can be provided to clients of this server in		 * lieu of the self signed certificate in order to		 * validate the public key.		 */		case CRYPTO_SIGN | CRYPTO_RESP:			/*			 * Discard the message if invalid or not			 * proventic.			 */			if (!(peer->crypto & CRYPTO_FLAG_PROV)) {				rval = XEVNT_ERR;				break;			}			if ((rval = crypto_verify(ep, NULL, peer)) !=			    XEVNT_OK)				break;			/*			 * Scan the certificate list to delete old			 * versions and link the newest version first on			 * the list.			 */			if ((rval = cert_install(ep, peer)) != XEVNT_OK)				break;			peer->crypto |= CRYPTO_FLAG_SIGN;			peer->flash &= ~TEST8;			temp32 = cinfo->nid;			sprintf(statstr, "sign %s 0x%x %s (%u) fs %u",			    cinfo->issuer, cinfo->flags,			    OBJ_nid2ln(temp32), temp32,			    ntohl(ep->fstamp));			record_crypto_stats(&peer->srcadr, statstr);#ifdef DEBUG			if (debug)				printf("crypto_recv: %s\n", statstr);#endif			break;		/*		 * Install leapseconds table in symmetric modes. This		 * table is proventicated to the NIST primary servers,		 * either by copying the file containing the table from		 * a NIST server to a trusted server or directly using		 * this protocol. While the entire table is installed at		 * the server, presently only the current TAI offset is		 * provided via the kernel to other applications.		 */		case CRYPTO_TAI:			/*			 * Discard the message if invalid.			 */			if ((rval = crypto_verify(ep, NULL, peer)) !=			    XEVNT_OK)				break;			/*			 * Pass the extension field to the transmit			 * side. Continue below if a leapseconds table			 * accompanies the message.			 */			fp = emalloc(len);			memcpy(fp, ep, len);			temp32 = CRYPTO_RESP;			fp->opcode |= htonl(temp32);			peer->cmmd = fp;			if (len <= VALUE_LEN) {				peer->flash &= ~TEST8;				break;			}			/* fall through */		case CRYPTO_TAI | CRYPTO_RESP:			/*			 * If this is a response, discard the message if			 * signature not verified with respect to the			 * leapsecond table values.			 */			if (peer->cmmd == NULL) {				if ((rval = crypto_verify(ep,				    &peer->tai_leap, peer)) != XEVNT_OK)					break;			}			/*			 * Initialize peer variables with latest update.			 */			peer->tai_leap.tstamp = ep->tstamp;			peer->tai_leap.fstamp = ep->fstamp;			peer->tai_leap.vallen = ep->vallen;			/*			 * Install the new table if there is no stored			 * table or the new table is more recent than			 * the stored table. Since a filestamp may have			 * changed, recompute the signatures.			 */			if (ntohl(peer->tai_leap.fstamp) >			    ntohl(tai_leap.fstamp)) {				tai_leap.fstamp = ep->fstamp;				tai_leap.vallen = ep->vallen;				if (tai_leap.ptr != NULL)					free(tai_leap.ptr);				tai_leap.ptr = emalloc(vallen);				memcpy(tai_leap.ptr, ep->pkt, vallen);				crypto_update();			}			crypto_flags |= CRYPTO_FLAG_TAI;			peer->crypto |= CRYPTO_FLAG_LEAP;			peer->flash &= ~TEST8;			sprintf(statstr, "leap %u ts %u fs %u", vallen,			    ntohl(ep->tstamp), ntohl(ep->fstamp));			record_crypto_stats(&peer->srcadr, statstr);#ifdef DEBUG			if (debug)				printf("crypto_recv: %s\n", statstr);#endif			break;		/*		 * We come here in symmetric modes for miscellaneous		 * commands that have value fields but are processed on		 * the transmit side. All we need do here is check for		 * valid field length. Remaining checks are below and on		 * the transmit side.		 */		case CRYPTO_CERT:		case CRYPTO_IFF:		case CRYPTO_GQ:		case CRYPTO_MV:		case CRYPTO_SIGN:			if (len < VALUE_LEN) {				rval = XEVNT_LEN;				break;			}			/* fall through */		/*		 * We come here for miscellaneous requests and unknown		 * requests and responses. If an unknown response or		 * error, forget it. If a request, save the extension		 * field for later. Unknown requests will be caught on		 * the transmit side.		 */		default:			if (code & (CRYPTO_RESP | CRYPTO_ERROR)) {				rval = XEVNT_ERR;			} else if ((rval = crypto_verify(ep, NULL,			    peer)) == XEVNT_OK) {				fp = emalloc(len);				memcpy(fp, ep, len);				temp32 = CRYPTO_RESP;				fp->opcode |= htonl(temp32);				peer->cmmd = fp;			}		}		/*		 * We don't log length/format/timestamp errors and		 * duplicates, which are log clogging vulnerabilities.		 * The first error found terminates the extension field		 * scan and we return the laundry to the caller. A		 * length/format/timestamp error on transmit is		 * cheerfully ignored, as the message is not sent.		 */		if (rval > XEVNT_TSP) {			sprintf(statstr,			    "error %x opcode %x ts %u fs %u", rval,			    code, tstamp, fstamp);			record_crypto_stats(&peer->srcadr, statstr);			report_event(rval, peer);#ifdef DEBUG			if (debug)				printf("crypto_recv: %s\n", statstr);#endif			break;		} else if (rval > XEVNT_OK && (code & CRYPTO_RESP)) {			rval = XEVNT_OK;		}		authlen += len;	}	return (rval);}/* * crypto_xmit - construct extension fields * * This routine is called both when an association is configured and * when one is not. The only case where this matters is to retrieve the * autokey information, in which case the caller has to provide the * association ID to match the association. * * Returns length of extension field. */intcrypto_xmit(	struct pkt *xpkt,	/* transmit packet pointer */	struct sockaddr_storage *srcadr_sin,	/* active runway */	int	start,		/* offset to extension field */	struct exten *ep,	/* extension pointer */	keyid_t cookie		/* session cookie */	){	u_int32	*pkt;		/* packet pointer */	struct peer *peer;	/* peer structure pointer */	u_int	opcode;		/* extension field opcode */	struct exten *fp;	/* extension pointers */	struct cert_info *cp, *xp; /* certificate info/value pointer */	char	certname[MAXHOSTNAME + 1]; /* subject name buffer */	char	statstr[NTP_MAXSTRLEN]; /* statistics for filegen */	tstamp_t tstamp;	u_int	vallen;	u_int	len;	struct value vtemp;	associd_t associd;	int	rval;	keyid_t tcookie;	/*	 * Generate the requested extension field request code, length	 * and association ID. If this is a response and the host is not	 * synchronized, light the error bit and go home.	 */	pkt = (u_int32 *)xpkt + start / 4;	fp = (struct exten *)pkt;	opcode = ntohl(ep->opcode);	associd = (associd_t) ntohl(ep->associd);	fp->associd = htonl(associd);	len = 8;	rval = XEVNT_OK;	tstamp = crypto_time();	switch (opcode & 0xffff0000) {	/*	 * Send association request and response with status word and	 * host name. Note, this message is not signed and the filestamp	 * contains only the status word.	 */	case CRYPTO_ASSOC | CRYPTO_RESP:		len += crypto_send(fp, &hostval);		fp->fstamp = htonl(crypto_flags);		break;	case CRYPTO_ASSOC:		len += crypto_send(fp, &hostval);		fp->fstamp = htonl(crypto_flags | ident_scheme);		break;	/*	 * Send certificate request. Use the values from the extension	 * field.	 */	case CRYPTO_CERT:		memset(&vtemp, 0, sizeof(vtemp));		vtemp.tstamp = ep->tstamp;		vtemp.fstamp = ep->fstamp;		vtemp.vallen = ep->vallen;		vtemp.ptr = (u_char *)ep->pkt;		len += crypto_send(fp, &vtemp);		break;	/*	 * Send certificate response or sign request. Use the values	 * from the certificate cache. If the request contains no	 * subject name, assume the name of this host. This is for	 * backwards compatibility. Private certificates are never sent.	 */	case CRYPTO_SIGN:	case CRYPTO_CERT | CRYPTO_RESP:		vallen = ntohl(ep->vallen);		if (vallen == 8) {			strcpy(certname, sys_hostname);		} else if (vallen == 0 || vallen > MAXHOSTNAME) {			rval = XEVNT_LEN;			break;		} else {			memcpy(certname, ep->pkt, vallen);			certname[vallen] = '\0';		}		/*		 * Find all certificates with matching subject. If a		 * self-signed, trusted certificate is found, use that.		 * If not, use the first one with matching subject. A		 * private certificate is never divulged or signed.		 */		xp = NULL;		for (cp = cinfo; cp != NULL; cp = cp->link) {			if (cp->flags & CERT_PRIV)				continue;			if (strcmp(certname, cp->subject) == 0) {				if (xp == NULL)					xp = cp;				if (strcmp(certname, cp->issuer) ==				    0 && cp->flags & CERT_TRUST) {					xp = cp;					break;				}			}		}		/*		 * Be careful who you trust. If not yet synchronized,		 * give back an empty response. If certificate not found		 * or beyond the lifetime, return an error. This is to		 * avoid a bad dude trying to get an expired certificate		 * re-signed. Otherwise, send it.		 *		 * Note the timestamp and filestamp are taken from the		 * certificate value structure. For all certificates the		 * timestamp is the latest signature update time. For		 * host and imported certificates the filestamp is the		 * creation epoch. For signed certificates the filestamp		 * is the creation epoch of the trusted certificate at		 * the base of the certificate trail. In principle, this		 * allows strong checking for signature masquerade.		 */		if (tstamp == 0)			break;		if (xp == NULL)			rval = XEVNT_CRT;		else if (tstamp < xp->first || tstamp > xp->last)			rval = XEVNT_SRV;		else			len += crypto_send(fp, &xp->cert);		break;	/*	 * Send challenge in Schnorr (IFF) identity scheme.	 */	case CRYPTO_IFF:		if ((peer = findpeerbyassoc(ep->pkt[0])) == NULL) {			rval = XEVNT_ERR;			break;		}		if ((rval = crypto_alice(peer, &vtemp)) == XEVNT_OK) {			len += crypto_send(fp, &vtemp);			value_free(&vtemp);		}		break;	/*	 * Send response in Schnorr (IFF) identity scheme.	 */	case CRYPTO_IFF | CRYPTO_RESP:		if ((rval = crypto_bob(ep, &vtemp)) == XEVNT_OK) {			len += crypto_send(fp, &vtemp);			value_free(&vtemp);		}		break;	/*	 * Send challenge in Guillou-Quisquater (GQ) identity scheme.	 */	case CRYPTO_GQ:		if ((peer = findpeerbyassoc(ep->pkt[0])) == NULL) {			rval = XEVNT_ERR;			break;		}		if ((rval = crypto_alice2(peer, &vtemp)) == XEVNT_OK) {			len += crypto_send(fp, &vtemp);			value_free(&vtemp);		}		break;	/*	 * Send response in Guillou-Quisquater (GQ) identity scheme.	 */	case CRYPTO_GQ | CRYPTO_RESP:		if ((rval = crypto_bob2(ep, &vtemp)) == XEVNT_OK) {			len += crypto_send(fp, &vtemp);			value_free(&vtemp);		}		break;	/*	 * Send challenge in MV identity scheme.	 */	case CRYPTO_MV:		if ((peer = findpeerbyassoc(ep->pkt[0])) == NULL) {			rval = XEVNT_ERR;			break;		}		if ((rval = crypto_alice3(peer, &vtemp)) == XEVNT_OK) {			len += crypto_send(fp, &vtemp);			value_free(&vtemp);		}		break;	/*	 * Send response in MV identity scheme.	 */	case CRYPTO_MV | CRYPTO_RESP:		if ((rval = crypto_bob3(ep, &vtemp)) == XEVNT_OK) {			len += crypto_send(fp, &vtemp);			value_free(&vtemp);		}		break;	/*	 * Send certificate sign response. The integrity of the request	 * certificate has already been verified on the receive side.	 * Sign the response using the local server key. Use the	 * filestamp from the request and use the timestamp as the	 * current time. Light the error bit if the certificate is	 * invalid or contains an unverified signature.	 */	case CRYPTO_SIGN | CRYPTO_RESP:		if ((rval = cert_sign(ep, &vtemp)) == XEVNT_OK)			len += crypto_send(fp, &vtemp);		value_free(&vtemp);		break;	/*	 * Send public key and signature. Use the values from the public	 * key.	 */	case CRYPTO_COOK:		len += crypto_send(fp, &pubkey);		break;	/*	 * Encrypt and send cookie and signature. Light the error bit if	 * anything goes wrong.	 */	case CRYPTO_COOK | CRYPTO_RESP:		if ((opcode & 0xffff) < VALUE_LEN) {			rval = XEVNT_LEN;			break;		}		if (PKT_MODE(xpkt->li_vn_mode) == MODE_SERVER) {			tcookie = cookie;		} else {			if ((peer = findpeerbyassoc(associd)) == NULL) {				rval = XEVNT_ERR;				break;			}			tcookie = peer->pcookie;		}

⌨️ 快捷键说明

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