ipsec_rcv.c

来自「FREESWAN VPN源代码包」· C语言 代码 · 共 2,240 行 · 第 1/5 页

C
2,240
字号
					    sa_len ? sa : " (error)");			} else {				KLIPS_PRINT(debug_rcv,					    "klips_debug:ipsec_rcv: "					    "SA:%s First SA in group.\n",					    sa_len ? sa : " (error)");			}						if(tdbp->tdb_onext) {				if(tdbprev != tdbp->tdb_onext) {					spin_unlock(&tdb_lock);					KLIPS_PRINT(debug_rcv,						    "klips_debug:ipsec_rcv: "						    "unexpected SA:%s: does not agree with tdb->onext policy, dropped.\n",						    sa_len ? sa : " (error)");					if(stats) {						stats->rx_dropped++;					}					goto rcvleave;				} else {					KLIPS_PRINT(debug_rcv,						    "klips_debug:ipsec_rcv: "						    "SA:%s grouping to previous SA is OK.\n",						    sa_len ? sa : " (error)");				}			} else {				KLIPS_PRINT(debug_rcv,					    "klips_debug:ipsec_rcv: "					    "SA:%s No previous backlink in group.\n",					    sa_len ? sa : " (error)");			}#ifdef CONFIG_IPSEC_NAT_TRAVERSAL			KLIPS_PRINT(debug_rcv,				"klips_debug:ipsec_rcv: "				"natt_type=%u tdbp->ips_natt_type=%u : %s\n",				natt_type, tdbp->ips_natt_type,				(natt_type==tdbp->ips_natt_type)?"ok":"bad");			if (natt_type != tdbp->ips_natt_type) {				spin_unlock(&tdb_lock);				KLIPS_PRINT(debug_rcv,					    "klips_debug:ipsec_rcv: "					    "SA:%s does not agree with expected NAT-T policy.\n",					    sa_len ? sa : " (error)");				if(stats) {					stats->rx_dropped++;				}				goto rcvleave;			}#endif		}				/* If it is in larval state, drop the packet, we cannot process yet. */		if(tdbp->tdb_state == SADB_SASTATE_LARVAL) {			spin_unlock(&tdb_lock);			KLIPS_PRINT(debug_rcv,				    "klips_debug:ipsec_rcv: "				    "TDB in larval state, cannot be used yet, dropping packet.\n");			if(stats) {				stats->rx_dropped++;			}			goto rcvleave;		}				if(tdbp->tdb_state == SADB_SASTATE_DEAD) {			spin_unlock(&tdb_lock);			KLIPS_PRINT(debug_rcv,				    "klips_debug:ipsec_rcv: "				    "TDB in dead state, cannot be used any more, dropping packet.\n");			if(stats) {				stats->rx_dropped++;			}			goto rcvleave;		}				if(ipsec_lifetime_check(&tdbp->ips_life.ipl_bytes,   "bytes", sa,					ipsec_life_countbased, ipsec_incoming, tdbp) == ipsec_life_harddied ||		   ipsec_lifetime_check(&tdbp->ips_life.ipl_addtime, "addtime",sa,					ipsec_life_timebased,  ipsec_incoming, tdbp) == ipsec_life_harddied ||		   ipsec_lifetime_check(&tdbp->ips_life.ipl_addtime, "usetime",sa,					ipsec_life_timebased,  ipsec_incoming, tdbp) == ipsec_life_harddied ||		   ipsec_lifetime_check(&tdbp->ips_life.ipl_packets, "packets",sa, 					ipsec_life_countbased, ipsec_incoming, tdbp) == ipsec_life_harddied) {			ipsec_sa_delchain(tdbp);			spin_unlock(&tdb_lock);			if(stats) {				stats->rx_dropped++;			}			goto rcvleave;		}		/* authenticate, if required */		idat = dat + iphlen;#ifdef CONFIG_IPSEC_ALG		if ((ixt_a=IPSEC_ALG_SA_ESP_AUTH(tdbp))) {			authlen = AHHMAC_HASHLEN;			KLIPS_PRINT(debug_rcv,					"klips_debug:ipsec_rcv: "					"authalg=%d authlen=%d\n",					tdbp->tdb_authalg, authlen);		} else#endif /* CONFIG_IPSEC_ALG */		switch(tdbp->tdb_authalg) {#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5		case AH_MD5:			authlen = AHHMAC_HASHLEN;			break;#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1		case AH_SHA:			authlen = AHHMAC_HASHLEN;			break;#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */		case AH_NONE:			authlen = 0;			break;		default:			tdbp->tdb_alg_errs += 1;			spin_unlock(&tdb_lock);			if(stats) {				stats->rx_errors++;			}			goto rcvleave;		}		ilen = len - iphlen - authlen;		if(ilen <= 0) {			spin_unlock(&tdb_lock);			KLIPS_PRINT(debug_rcv,				    "klips_debug:ipsec_rcv: "				    "runt AH packet with no data, dropping.\n");			if(stats) {				stats->rx_dropped++;			}			goto rcvleave;		}		#ifdef CONFIG_IPSEC_ESP		KLIPS_PRINT(proto == IPPROTO_ESP && debug_rcv, 			    "klips_debug:ipsec_rcv: "			    "packet from %s received with seq=%d (iv)=0x%08x%08x iplen=%d esplen=%d sa=%s\n",			    ipaddr_txt,			    (__u32)ntohl(espp->esp_rpl),			    (__u32)ntohl(*((__u32 *)(espp->esp_iv)    )),			    (__u32)ntohl(*((__u32 *)(espp->esp_iv) + 1)),			    len,			    ilen,			    sa_len ? sa : " (error)");#endif /* !CONFIG_IPSEC_ESP */				switch(proto) {#ifdef CONFIG_IPSEC_ESP		case IPPROTO_ESP:			replay = ntohl(espp->esp_rpl);			authenticator = &(dat[len - authlen]);			break;#endif /* !CONFIG_IPSEC_ESP */#ifdef CONFIG_IPSEC_AH		case IPPROTO_AH:			replay = ntohl(ahp->ah_rpl);			authenticator = ahp->ah_data;			break;#endif /* CONFIG_IPSEC_AH */		}		if (!ipsec_checkreplaywindow(tdbp, replay)) {			tdbp->tdb_replaywin_errs += 1;			spin_unlock(&tdb_lock);			KLIPS_PRINT(debug_rcv & DB_RX_REPLAY,				    "klips_debug:ipsec_rcv: "				    "duplicate frame from %s, packet dropped\n",				    ipaddr_txt);			if(stats) {				stats->rx_dropped++;			}			goto rcvleave;		}				/*		 * verify authenticator		 */				KLIPS_PRINT(debug_rcv,			    "klips_debug:ipsec_rcv: "			    "encalg = %d, authalg = %d.\n",			    tdbp->tdb_encalg,			    tdbp->tdb_authalg);		#ifdef CONFIG_IPSEC_ALG		if (ixt_a) {			KLIPS_PRINT(debug_rcv,					"klips_debug:ipsec_rcv: "					"ipsec_alg hashing ... ");			if(proto == IPPROTO_ESP) {				ipsec_alg_sa_esp_hash(tdbp,						(caddr_t)espp, ilen,						hash, AHHMAC_HASHLEN);#ifdef CONFIG_IPSEC_AH#ifdef IPSEC_ALG_WHEN_AH_IS_READY			} else {				ipo = *ipp;				ipo.tos = 0;				ipo.frag_off = 0;				ipo.ttl = 0;				ipo.check = 0;				ipsec_alg_hmac_update(tdbp->tdb_key_a,						(caddr_t)&ipo, 						sizeof(struct iphdr));				ipsec_alg_hmac_update(tdbp->tdb_key_a,						(caddr_t)ahp,						ahhlen - AHHMAC_HASHLEN);				ipsec_alg_hmac_update(tdbp->tdb_key_a,						(caddr_t)zeroes,						AHHMAC_HASHLEN);				ipsec_alg_hmac_hash(tdbp->tdb_key_a,						(caddr_t)dat + iphlen + ahhlen,						len - iphlen - ahhlen,						hash, AHHMAC_HASHLEN);#endif#endif /* CONFIG_IPSEC_AH */			}		} else#endif /* CONFIG_IPSEC_ALG */		if(tdbp->tdb_authalg) {			switch(tdbp->tdb_authalg) {#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5			case AH_MD5:				tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->ictx;				if(proto == IPPROTO_ESP) {					MD5Update(&tctx.md5, (caddr_t)espp, ilen);#ifdef CONFIG_IPSEC_AH				} else {					ipo = *ipp;					ipo.tos = 0;	/* mutable RFC 2402 3.3.3.1.1.1 */					ipo.frag_off = 0;					ipo.ttl = 0;					ipo.check = 0;										MD5Update(&tctx.md5, (caddr_t)&ipo,						  sizeof(struct iphdr));					MD5Update(&tctx.md5, (caddr_t)ahp,						  ahhlen - AHHMAC_HASHLEN);					MD5Update(&tctx.md5, (caddr_t)zeroes,						  AHHMAC_HASHLEN);					MD5Update(&tctx.md5,						  (caddr_t)dat + iphlen + ahhlen,						  len - iphlen - ahhlen);#endif /* CONFIG_IPSEC_AH */				}				MD5Final(hash, &tctx.md5);				tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->octx;				MD5Update(&tctx.md5, hash, AHMD596_ALEN);				MD5Final(hash, &tctx.md5);				break;#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1			case AH_SHA:				tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->ictx;				if(proto == IPPROTO_ESP) {					SHA1Update(&tctx.sha1, (caddr_t)espp, ilen);#ifdef CONFIG_IPSEC_AH				} else {					ipo = *ipp;					ipo.tos = 0;					ipo.frag_off = 0;					ipo.ttl = 0;					ipo.check = 0;										SHA1Update(&tctx.sha1, (caddr_t)&ipo,						   sizeof(struct iphdr));					SHA1Update(&tctx.sha1, (caddr_t)ahp,						   ahhlen - AHHMAC_HASHLEN);					SHA1Update(&tctx.sha1, (caddr_t)zeroes,						   AHHMAC_HASHLEN);					SHA1Update(&tctx.sha1,						   (caddr_t)dat + iphlen + ahhlen,						   len - iphlen - ahhlen);#endif /* CONFIG_IPSEC_AH */				}				SHA1Final(hash, &tctx.sha1);				tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->octx;				SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN);				SHA1Final(hash, &tctx.sha1);				break;#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */			case AH_NONE:				break;			}					if(!authenticator) {				tdbp->tdb_auth_errs += 1;				spin_unlock(&tdb_lock);				if(stats) {					stats->rx_dropped++;				}				goto rcvleave;			}			if (memcmp(hash, authenticator, authlen)) {				tdbp->tdb_auth_errs += 1;				spin_unlock(&tdb_lock);				KLIPS_PRINT(debug_rcv & DB_RX_INAU,					    "klips_debug:ipsec_rcv: "					    "auth failed on incoming packet from %s: hash=%08x%08x%08x auth=%08x%08x%08x, dropped\n",					    ipaddr_txt,					    *(__u32*)&hash[0],					    *(__u32*)&hash[4],					    *(__u32*)&hash[8],					    *(__u32*)authenticator,					    *((__u32*)authenticator + 1),					    *((__u32*)authenticator + 2));				if(stats) {					stats->rx_dropped++;				}				goto rcvleave;			} else {				KLIPS_PRINT(debug_rcv,					    "klips_debug:ipsec_rcv: "					    "authentication successful.\n");			}						memset((caddr_t)&tctx, 0, sizeof(tctx));			memset(hash, 0, sizeof(hash));		}		/* If the sequence number == 0, expire SA, it had rolled */		if(tdbp->tdb_replaywin && !replay /* !tdbp->tdb_replaywin_lastseq */) {			ipsec_sa_delchain(tdbp);			spin_unlock(&tdb_lock);			KLIPS_PRINT(debug_rcv,				    "klips_debug:ipsec_rcv: "				    "replay window counter rolled, expiring SA.\n");			if(stats) {				stats->rx_dropped++;			}			goto rcvleave;		}		if (!ipsec_updatereplaywindow(tdbp, replay)) {			tdbp->tdb_replaywin_errs += 1;			spin_unlock(&tdb_lock);			KLIPS_PRINT(debug_rcv & DB_RX_REPLAY,				    "klips_debug:ipsec_rcv: "				    "duplicate frame from %s, packet dropped\n",				    ipaddr_txt);			if(stats) {				stats->rx_dropped++;			}			goto rcvleave;		}				switch(proto) {#ifdef CONFIG_IPSEC_ESP		case IPPROTO_ESP:#ifdef CONFIG_IPSEC_ALG			if ((ixt_e=IPSEC_ALG_SA_ESP_ENC(tdbp))) {				esphlen = ESP_HEADER_LEN + ixt_e->ixt_ivlen/8;				KLIPS_PRINT(debug_rcv,						"klips_debug:ipsec_rcv: "						"encalg=%d esphlen=%d\n",						tdbp->tdb_encalg, esphlen);			} else#endif /* CONFIG_IPSEC_ALG */			switch(tdbp->tdb_encalg) {#ifdef CONFIG_IPSEC_ENC_3DES			case ESP_3DES:				iv[0] = *((__u32 *)(espp->esp_iv)    );				iv[1] = *((__u32 *)(espp->esp_iv) + 1);				esphlen = sizeof(struct esp);				break;#endif /* CONFIG_IPSEC_ENC_3DES */			default:				tdbp->tdb_alg_errs += 1;				spin_unlock(&tdb_lock);				if(stats) {					stats->rx_errors++;				}				goto rcvleave;			}			idat += esphlen;			ilen -= esphlen;			#ifdef CONFIG_IPSEC_ALG			if (ixt_e)			{				if (ipsec_alg_esp_encrypt(tdbp, 					idat, ilen, espp->esp_iv, 					IPSEC_ALG_DECRYPT) <= 0)				{					spin_unlock(&tdb_lock);					printk("klips_error:ipsec_rcv: "						"got packet with esplen = %d "						"from %s -- should be on "						"ENC(%d) octet boundary, "						"packet dropped\n",							ilen,							ipaddr_txt,							tdbp->tdb_encalg);					stats->rx_errors++;					goto rcvleave;				}			} else#endif /* CONFIG_IPSEC_ALG */			switch(tdbp->tdb_encalg) {#ifdef CONFIG_IPSEC_ENC_3DES			case ESP_3DES:				if ((ilen) % 8) {					tdbp->tdb_encsize_errs += 1;					spin_unlock(&tdb_lock);					printk("klips_error:ipsec_rcv: "					       "got packet with esplen = %d from %s -- should be on 8 octet boundary, packet dropped\n",					       ilen,					       ipaddr_txt);					if(stats) {						stats->rx_errors++;					}					goto rcvleave;				}				des_ede3_cbc_encrypt((des_cblock *)idat,						     (des_cblock *)idat,						     ilen,						     ((struct des_eks *)(tdbp->tdb_key_e))[0].ks,						     ((struct des_eks *)(tdbp->tdb_key_e))[1].ks,						     ((struct des_eks *)(tdbp->tdb_key_e))[2].ks,						     (des_cblock *)iv, 0);				break;#endif /* CONFIG_IPSEC_ENC_3DES */			default:			}			next_header = idat[ilen - 1];			padlen = idat[ilen - 2];			pad = padlen + 2 + authlen;			{			        int badpad = 0;								KLIPS_PRINT(debug_rcv & DB_RX_IPAD,					    "klips_debug:ipsec_rcv: "					    "padlen=%d, contents: 0x<offset>: 0x<value> 0x<value> ...\n",					    padlen);								for (i = 1; i <= padlen; i++) {					if((i % 16) == 1) {						KLIPS_PRINT(debug_rcv & DB_RX_IPAD,							    "klips_debug:           %02x:",							    i - 1);					}					KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD,						    " %02x",						    idat[ilen - 2 - padlen + i - 1]);

⌨️ 快捷键说明

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