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 + -
显示快捷键?