/* * Verify that the skb can go out on this ipsp. * Return 0 if OK, error code otherwise. */ static int ipsec_mast_check_outbound_policy(struct ipsec_xmit_state *ixs) { int failed_outbound_check = 0; struct ipsec_sa *ipsp = ixs->ipsp; if (!ixs || !ixs->ipsp || !ixs->iph) return -EFAULT; /* Note: "xor" (^) logically replaces "not equal" * (!=) and "bitwise or" (|) logically replaces * "boolean or" (||). This is done to speed up * execution by doing only bitwise operations and * no branch operations */ if (osw_ip_hdr_version(ixs) == 4) { struct iphdr *ipp = osw_ip4_hdr(ixs); if (ip_address_family(&ipsp->ips_said.dst) != AF_INET) { failed_outbound_check = 1; } else if (((ipp->saddr & ipsp->ips_mask_s.u.v4.sin_addr.s_addr) ^ ipsp->ips_flow_s.u.v4.sin_addr.s_addr) | ((ipp->daddr & ipsp->ips_mask_d.u.v4.sin_addr.s_addr) ^ ipsp->ips_flow_d.u.v4.sin_addr.s_addr)) { failed_outbound_check = 1; } } else if (osw_ip_hdr_version(ixs) == 6) { struct ipv6hdr *ipp6 = osw_ip6_hdr(ixs); if (ip_address_family(&ipsp->ips_said.dst) != AF_INET6) { failed_outbound_check = 1; } else if (((ipp6->saddr.s6_addr32[0] & ipsp->ips_mask_s.u.v6.sin6_addr.s6_addr32[0]) ^ ipsp->ips_flow_s.u.v6.sin6_addr.s6_addr32[0]) | ((ipp6->daddr.s6_addr32[0] & ipsp->ips_mask_d.u.v6.sin6_addr.s6_addr32[0]) ^ ipsp->ips_flow_d.u.v6.sin6_addr.s6_addr32[0])) { failed_outbound_check = 1; } else if (((ipp6->saddr.s6_addr32[1] & ipsp->ips_mask_s.u.v6.sin6_addr.s6_addr32[1]) ^ ipsp->ips_flow_s.u.v6.sin6_addr.s6_addr32[1]) | ((ipp6->daddr.s6_addr32[1] & ipsp->ips_mask_d.u.v6.sin6_addr.s6_addr32[1]) ^ ipsp->ips_flow_d.u.v6.sin6_addr.s6_addr32[1])) { failed_outbound_check = 1; } else if (((ipp6->saddr.s6_addr32[2] & ipsp->ips_mask_s.u.v6.sin6_addr.s6_addr32[2]) ^ ipsp->ips_flow_s.u.v6.sin6_addr.s6_addr32[2]) | ((ipp6->daddr.s6_addr32[2] & ipsp->ips_mask_d.u.v6.sin6_addr.s6_addr32[2]) ^ ipsp->ips_flow_d.u.v6.sin6_addr.s6_addr32[2])) { failed_outbound_check = 1; } else if (((ipp6->saddr.s6_addr32[3] & ipsp->ips_mask_s.u.v6.sin6_addr.s6_addr32[3]) ^ ipsp->ips_flow_s.u.v6.sin6_addr.s6_addr32[3]) | ((ipp6->daddr.s6_addr32[3] & ipsp->ips_mask_d.u.v6.sin6_addr.s6_addr32[3]) ^ ipsp->ips_flow_d.u.v6.sin6_addr.s6_addr32[3])) { failed_outbound_check = 1; } } if (failed_outbound_check) { char saddr_txt[ADDRTOA_BUF], daddr_txt[ADDRTOA_BUF]; char sflow_txt[SUBNETTOA_BUF], dflow_txt[SUBNETTOA_BUF]; if (ipsp->ips_flow_s.u.v4.sin_family == AF_INET6) { subnet6toa(&ipsp->ips_flow_s.u.v6.sin6_addr, &ipsp->ips_mask_s.u.v6.sin6_addr, 0, sflow_txt, sizeof(sflow_txt)); subnet6toa(&ipsp->ips_flow_d.u.v6.sin6_addr, &ipsp->ips_mask_d.u.v6.sin6_addr, 0, dflow_txt, sizeof(dflow_txt)); inet_addrtot(AF_INET6, &osw_ip6_hdr(ixs)->saddr, 0, saddr_txt, sizeof(saddr_txt)); inet_addrtot(AF_INET6, &osw_ip6_hdr(ixs)->daddr, 0, daddr_txt, sizeof(daddr_txt)); } else { subnettoa(ipsp->ips_flow_s.u.v4.sin_addr, ipsp->ips_mask_s.u.v4.sin_addr, 0, sflow_txt, sizeof(sflow_txt)); subnettoa(ipsp->ips_flow_d.u.v4.sin_addr, ipsp->ips_mask_d.u.v4.sin_addr, 0, dflow_txt, sizeof(dflow_txt)); inet_addrtot(AF_INET, &osw_ip4_hdr(ixs)->saddr, 0, saddr_txt, sizeof(saddr_txt)); inet_addrtot(AF_INET, &osw_ip4_hdr(ixs)->daddr, 0, daddr_txt, sizeof(daddr_txt)); } if (!ixs->sa_len) ixs->sa_len = KLIPS_SATOT(debug_mast, &ixs->outgoing_said, 0, ixs->sa_txt, sizeof(ixs->sa_txt)); KLIPS_PRINT(debug_mast, "klips_debug:ipsec_mast_check_outbound_policy: " "SA:%s, inner tunnel policy [%s -> %s] does not agree with pkt contents [%s -> %s].\n", ixs->sa_len ? ixs->sa_txt : " (error)", sflow_txt, dflow_txt, saddr_txt, daddr_txt); if(ixs->stats) ixs->stats->rx_dropped++; return -EACCES; } #if 0 { char sflow_txt[SUBNETTOA_BUF], dflow_txt[SUBNETTOA_BUF]; char saddr_txt[ADDRTOA_BUF], daddr_txt[ADDRTOA_BUF]; struct in_addr ipaddr; subnettoa(ixs->ipsp->ips_flow_s.u.v4.sin_addr, ixs->ipsp->ips_mask_s.u.v4.sin_addr, 0, sflow_txt, sizeof(sflow_txt)); subnettoa(ixs->ipsp->ips_flow_d.u.v4.sin_addr, ixs->ipsp->ips_mask_d.u.v4.sin_addr, 0, dflow_txt, sizeof(dflow_txt)); ipaddr.s_addr = ixs->iph->saddr; addrtoa(ipaddr, 0, saddr_txt, sizeof(saddr_txt)); ipaddr.s_addr = ixs->iph->daddr; addrtoa(ipaddr, 0, daddr_txt, sizeof(daddr_txt)); if (!ixs->sa_len) ixs->sa_len = KLIPS_SATOT(debug_mast, &ixs->outgoing_said, 0, ixs->sa_txt, sizeof(ixs->sa_txt)); KLIPS_PRINT(debug_mast, "klips_debug:ipsec_mast_check_outbound_policy: " "SA:%s, inner tunnel policy [%s -> %s] agrees with pkt contents [%s -> %s].\n", ixs->sa_len ? ixs->sa_txt : " (error)", sflow_txt, dflow_txt, saddr_txt, daddr_txt); } #endif return 0; }
void ipsec_print_ip(struct iphdr *ip) { char buf[ADDRTOA_BUF]; printk(KERN_INFO "klips_debug: IP:"); printk(" ihl:%d", ip->ihl << 2); printk(" ver:%d", ip->version); printk(" tos:%d", ip->tos); printk(" tlen:%d", ntohs(ip->tot_len)); printk(" id:%d", ntohs(ip->id)); printk(" %s%s%sfrag_off:%d", ip->frag_off & __constant_htons(IP_CE) ? "CE " : "", ip->frag_off & __constant_htons(IP_DF) ? "DF " : "", ip->frag_off & __constant_htons(IP_MF) ? "MF " : "", (ntohs(ip->frag_off) & IP_OFFSET) << 3); printk(" ttl:%d", ip->ttl); printk(" proto:%d", ip->protocol); if(ip->protocol == IPPROTO_UDP) printk(" (UDP)"); if(ip->protocol == IPPROTO_TCP) printk(" (TCP)"); if(ip->protocol == IPPROTO_ICMP) printk(" (ICMP)"); printk(" chk:%d", ntohs(ip->check)); addrtoa(*((struct in_addr*)(&ip->saddr)), 0, buf, sizeof(buf)); printk(" saddr:%s", buf); if(ip->protocol == IPPROTO_UDP) printk(":%d", ntohs(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->source)); if(ip->protocol == IPPROTO_TCP) printk(":%d", ntohs(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->source)); addrtoa(*((struct in_addr*)(&ip->daddr)), 0, buf, sizeof(buf)); printk(" daddr:%s", buf); if(ip->protocol == IPPROTO_UDP) printk(":%d", ntohs(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest)); if(ip->protocol == IPPROTO_TCP) printk(":%d", ntohs(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest)); if(ip->protocol == IPPROTO_ICMP) printk(" type:code=%d:%d", ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->type, ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->code); printk("\n"); if(sysctl_ipsec_debug_verbose) { __u8 *c; int i; c = ((__u8*)ip) + ip->ihl*4; for(i = 0; i < ntohs(ip->tot_len) - ip->ihl*4; i++ /*, c++*/) { if(!(i % 16)) { printk(KERN_INFO "klips_debug: @%03x:", i); } printk(" %02x", /***/c[i]); if(!((i + 1) % 16)) { printk("\n"); } } if(i % 16) { printk("\n"); } } }
DEBUG_NO_STATIC int pfkey_address_parse(struct sadb_ext *pfkey_ext) { int error = 0; int saddr_len = 0; struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext; struct sockaddr* s = (struct sockaddr*)((char*)pfkey_address + sizeof(*pfkey_address)); char ipaddr_txt[ADDRTOT_BUF]; /* sanity checks... */ if(!pfkey_address) { ERROR( "pfkey_address_parse: " "NULL pointer passed in.\n"); SENDERR(EINVAL); } if(pfkey_address->sadb_address_len < (sizeof(struct sadb_address) + sizeof(struct sockaddr))/ IPSEC_PFKEYv2_ALIGN) { ERROR("pfkey_address_parse: " "size wrong 1 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n", pfkey_address->sadb_address_len, (int)sizeof(struct sadb_address), (int)sizeof(struct sockaddr)); SENDERR(EINVAL); } if(pfkey_address->sadb_address_reserved) { ERROR("pfkey_address_parse: " "res=%d, must be zero.\n", pfkey_address->sadb_address_reserved); SENDERR(EINVAL); } switch(pfkey_address->sadb_address_exttype) { case K_SADB_EXT_ADDRESS_SRC: case K_SADB_EXT_ADDRESS_DST: case K_SADB_EXT_ADDRESS_PROXY: case K_SADB_X_EXT_ADDRESS_DST2: case K_SADB_X_EXT_ADDRESS_SRC_FLOW: case K_SADB_X_EXT_ADDRESS_DST_FLOW: case K_SADB_X_EXT_ADDRESS_SRC_MASK: case K_SADB_X_EXT_ADDRESS_DST_MASK: #ifdef NAT_TRAVERSAL case K_SADB_X_EXT_NAT_T_OA: #endif break; default: ERROR( "pfkey_address_parse: " "unexpected ext_type=%d.\n", pfkey_address->sadb_address_exttype); SENDERR(ENODEV); } switch(s->sa_family) { case AF_INET: saddr_len = sizeof(struct sockaddr_in); addrtoa(((struct sockaddr_in*)s)->sin_addr, 0, ipaddr_txt, sizeof(ipaddr_txt)); DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_address_parse: " "found exttype=%u(%s) family=%d(AF_INET) address=%s proto=%u port=%u.\n", pfkey_address->sadb_address_exttype, pfkey_v2_sadb_ext_string(pfkey_address->sadb_address_exttype), s->sa_family, ipaddr_txt, pfkey_address->sadb_address_proto, ntohs(((struct sockaddr_in*)s)->sin_port)); break; case AF_INET6: saddr_len = sizeof(struct sockaddr_in6); sprintf(ipaddr_txt, "%x:%x:%x:%x:%x:%x:%x:%x" , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[0]) , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[1]) , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[2]) , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[3]) , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[4]) , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[5]) , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[6]) , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[7])); DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_address_parse: " "found exttype=%u(%s) family=%d(AF_INET6) address=%s proto=%u port=%u.\n", pfkey_address->sadb_address_exttype, pfkey_v2_sadb_ext_string(pfkey_address->sadb_address_exttype), s->sa_family, ipaddr_txt, pfkey_address->sadb_address_proto, ((struct sockaddr_in6*)s)->sin6_port); break; default: ERROR( "pfkey_address_parse: " "s->sa_family=%d not supported.\n", s->sa_family); SENDERR(EPFNOSUPPORT); } if(pfkey_address->sadb_address_len != DIVUP(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)) { ERROR( "pfkey_address_parse: " "size wrong 2 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n", pfkey_address->sadb_address_len, (int)sizeof(struct sadb_address), saddr_len); SENDERR(EINVAL); } if(pfkey_address->sadb_address_prefixlen != 0) { ERROR( "pfkey_address_parse: " "address prefixes not supported yet.\n"); SENDERR(EAFNOSUPPORT); /* not supported yet */ } /* XXX check if port!=0 */ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, "pfkey_address_parse: successful.\n"); errlab: return error; }
int ipsec_sa_print(struct ipsec_sa *ips) { char sa[SATOT_BUF]; size_t sa_len; printk(KERN_INFO "klips_debug: SA:"); if(ips == NULL) { printk("NULL\n"); return -ENOENT; } printk(" ref=%d", ips->ips_ref); printk(" refcount=%d", atomic_read(&ips->ips_refcount)); if(ips->ips_hnext != NULL) { printk(" hnext=0p%p", ips->ips_hnext); } if(ips->ips_next != NULL) { printk(" next=0p%p", ips->ips_next); } sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); printk(" said=%s", sa_len ? sa : " (error)"); if(ips->ips_seq) { printk(" seq=%u", ips->ips_seq); } if(ips->ips_pid) { printk(" pid=%u", ips->ips_pid); } if(ips->ips_authalg) { printk(" authalg=%u", ips->ips_authalg); } if(ips->ips_encalg) { printk(" encalg=%u", ips->ips_encalg); } printk(" XFORM=%s%s%s", IPS_XFORM_NAME(ips)); if(ips->ips_replaywin) { printk(" ooowin=%u", ips->ips_replaywin); } if(ips->ips_flags) { printk(" flags=%u", ips->ips_flags); } if(ips->ips_addr_s) { char buf[SUBNETTOA_BUF]; addrtoa(((struct sockaddr_in*)(ips->ips_addr_s))->sin_addr, 0, buf, sizeof(buf)); printk(" src=%s", buf); } if(ips->ips_addr_d) { char buf[SUBNETTOA_BUF]; addrtoa(((struct sockaddr_in*)(ips->ips_addr_s))->sin_addr, 0, buf, sizeof(buf)); printk(" dst=%s", buf); } if(ips->ips_addr_p) { char buf[SUBNETTOA_BUF]; addrtoa(((struct sockaddr_in*)(ips->ips_addr_p))->sin_addr, 0, buf, sizeof(buf)); printk(" proxy=%s", buf); } if(ips->ips_key_bits_a) { printk(" key_bits_a=%u", ips->ips_key_bits_a); } if(ips->ips_key_bits_e) { printk(" key_bits_e=%u", ips->ips_key_bits_e); } printk("\n"); return 0; }
int ipsec_sa_init(struct ipsec_sa *ipsp) { int i; int error = 0; char sa[SATOT_BUF]; size_t sa_len; char ipaddr_txt[ADDRTOA_BUF]; char ipaddr2_txt[ADDRTOA_BUF]; #if defined (CONFIG_KLIPS_AUTH_HMAC_MD5) || defined (CONFIG_KLIPS_AUTH_HMAC_SHA1) unsigned char kb[AHMD596_BLKLEN]; #endif struct ipsec_alg_enc *ixt_e = NULL; struct ipsec_alg_auth *ixt_a = NULL; if(ipsp == NULL) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "ipsp is NULL, fatal\n"); SENDERR(EINVAL); } sa_len = KLIPS_SATOT(debug_pfkey, &ipsp->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "(pfkey defined) called for SA:%s\n", sa_len ? sa : " (error)"); KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "calling init routine of %s%s%s\n", IPS_XFORM_NAME(ipsp)); switch(ipsp->ips_said.proto) { #ifdef CONFIG_KLIPS_IPIP case IPPROTO_IPIP: { ipsp->ips_xformfuncs = ipip_xform_funcs; addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_s))->sin_addr, 0, ipaddr_txt, sizeof(ipaddr_txt)); addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr, 0, ipaddr2_txt, sizeof(ipaddr_txt)); KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "(pfkey defined) IPIP ipsec_sa set for %s->%s.\n", ipaddr_txt, ipaddr2_txt); } break; #endif /* !CONFIG_KLIPS_IPIP */ #ifdef CONFIG_KLIPS_AH case IPPROTO_AH: ipsp->ips_xformfuncs = ah_xform_funcs; switch(ipsp->ips_authalg) { # ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 case AH_MD5: { unsigned char *akp; unsigned int aks; MD5_CTX *ictx; MD5_CTX *octx; if(ipsp->ips_key_bits_a != (AHMD596_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "incorrect key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHMD596_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "hmac md5-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)ipsp->ips_key_a)+0)), ntohl(*(((__u32 *)ipsp->ips_key_a)+1)), ntohl(*(((__u32 *)ipsp->ips_key_a)+2)), ntohl(*(((__u32 *)ipsp->ips_key_a)+3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHMD596_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "allocating %lu bytes for md5_ctx.\n", (unsigned long) sizeof(struct md5_ctx)); if((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct md5_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { kb[i] = akp[i] ^ HMAC_IPAD; } for (; i < AHMD596_BLKLEN; i++) { kb[i] = HMAC_IPAD; } ictx = &(((struct md5_ctx*)(ipsp->ips_key_a))->ictx); osMD5Init(ictx); osMD5Update(ictx, kb, AHMD596_BLKLEN); for (i = 0; i < AHMD596_BLKLEN; i++) { kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); } octx = &(((struct md5_ctx*)(ipsp->ips_key_a))->octx); osMD5Init(octx); osMD5Update(octx, kb, AHMD596_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ /* zero key buffer -- paranoid */ memset(akp, 0, aks); kfree(akp); } break; # endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ # ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 case AH_SHA: { unsigned char *akp; unsigned int aks; SHA1_CTX *ictx; SHA1_CTX *octx; if(ipsp->ips_key_bits_a != (AHSHA196_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "incorrect key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHSHA196_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "hmac sha1-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)ipsp->ips_key_a)+0)), ntohl(*(((__u32 *)ipsp->ips_key_a)+1)), ntohl(*(((__u32 *)ipsp->ips_key_a)+2)), ntohl(*(((__u32 *)ipsp->ips_key_a)+3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHSHA196_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "allocating %lu bytes for sha1_ctx.\n", (unsigned long) sizeof(struct sha1_ctx)); if((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct sha1_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { kb[i] = akp[i] ^ HMAC_IPAD; } for (; i < AHMD596_BLKLEN; i++) { kb[i] = HMAC_IPAD; } ictx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->ictx); SHA1Init(ictx); SHA1Update(ictx, kb, AHSHA196_BLKLEN); for (i = 0; i < AHSHA196_BLKLEN; i++) { kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); } octx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->octx); SHA1Init(octx); SHA1Update(octx, kb, AHSHA196_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ /* zero key buffer -- paranoid */ memset(akp, 0, aks); kfree(akp); } break; # endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ default: KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "authalg=%d support not available in the kernel", ipsp->ips_authalg); SENDERR(EINVAL); } break; #endif /* CONFIG_KLIPS_AH */ #ifdef CONFIG_KLIPS_ESP case IPPROTO_ESP: ipsp->ips_xformfuncs = esp_xform_funcs; { #if defined (CONFIG_KLIPS_AUTH_HMAC_MD5) || defined (CONFIG_KLIPS_AUTH_HMAC_SHA1) unsigned char *akp; unsigned int aks; #endif ipsec_alg_sa_init(ipsp); ixt_e=ipsp->ips_alg_enc; if (ixt_e == NULL) { if(printk_ratelimit()) { printk(KERN_ERR "ipsec_sa_init: " "encalg=%d support not available in the kernel", ipsp->ips_encalg); } SENDERR(ENOENT); } ipsp->ips_iv_size = ixt_e->ixt_common.ixt_support.ias_ivlen/8; /* Create IV */ if (ipsp->ips_iv_size) { if((ipsp->ips_iv = (caddr_t) kmalloc(ipsp->ips_iv_size, GFP_ATOMIC)) == NULL) { SENDERR(ENOMEM); } prng_bytes(&ipsec_prng, (char *)ipsp->ips_iv, ipsp->ips_iv_size); ipsp->ips_iv_bits = ipsp->ips_iv_size * 8; } if ((error=ipsec_alg_enc_key_create(ipsp)) < 0) SENDERR(-error); if ((ixt_a=ipsp->ips_alg_auth)) { if ((error=ipsec_alg_auth_key_create(ipsp)) < 0) SENDERR(-error); } else switch(ipsp->ips_authalg) { # ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 case AH_MD5: { MD5_CTX *ictx; MD5_CTX *octx; if(ipsp->ips_key_bits_a != (AHMD596_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "incorrect authorisation key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHMD596_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "hmac md5-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)(ipsp->ips_key_a))+0)), ntohl(*(((__u32 *)(ipsp->ips_key_a))+1)), ntohl(*(((__u32 *)(ipsp->ips_key_a))+2)), ntohl(*(((__u32 *)(ipsp->ips_key_a))+3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHMD596_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "allocating %lu bytes for md5_ctx.\n", (unsigned long) sizeof(struct md5_ctx)); if((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct md5_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { kb[i] = akp[i] ^ HMAC_IPAD; } for (; i < AHMD596_BLKLEN; i++) { kb[i] = HMAC_IPAD; } ictx = &(((struct md5_ctx*)(ipsp->ips_key_a))->ictx); osMD5Init(ictx); osMD5Update(ictx, kb, AHMD596_BLKLEN); for (i = 0; i < AHMD596_BLKLEN; i++) { kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); } octx = &(((struct md5_ctx*)(ipsp->ips_key_a))->octx); osMD5Init(octx); osMD5Update(octx, kb, AHMD596_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ /* paranoid */ memset(akp, 0, aks); kfree(akp); break; } # endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ # ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 case AH_SHA: { SHA1_CTX *ictx; SHA1_CTX *octx; if(ipsp->ips_key_bits_a != (AHSHA196_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "incorrect authorisation key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHSHA196_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "hmac sha1-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)ipsp->ips_key_a)+0)), ntohl(*(((__u32 *)ipsp->ips_key_a)+1)), ntohl(*(((__u32 *)ipsp->ips_key_a)+2)), ntohl(*(((__u32 *)ipsp->ips_key_a)+3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHSHA196_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "allocating %lu bytes for sha1_ctx.\n", (unsigned long) sizeof(struct sha1_ctx)); if((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct sha1_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { kb[i] = akp[i] ^ HMAC_IPAD; } for (; i < AHMD596_BLKLEN; i++) { kb[i] = HMAC_IPAD; } ictx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->ictx); SHA1Init(ictx); SHA1Update(ictx, kb, AHSHA196_BLKLEN); for (i = 0; i < AHSHA196_BLKLEN; i++) { kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); } octx = &((struct sha1_ctx*)(ipsp->ips_key_a))->octx; SHA1Init(octx); SHA1Update(octx, kb, AHSHA196_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ memset(akp, 0, aks); kfree(akp); break; } # endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ case AH_NONE: break; default: KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "authalg=%d support not available in the kernel.\n", ipsp->ips_authalg); SENDERR(EINVAL); } } break; #endif /* !CONFIG_KLIPS_ESP */ #ifdef CONFIG_KLIPS_IPCOMP case IPPROTO_COMP: ipsp->ips_xformfuncs = ipcomp_xform_funcs; ipsp->ips_comp_adapt_tries = 0; ipsp->ips_comp_adapt_skip = 0; ipsp->ips_comp_ratio_cbytes = 0; ipsp->ips_comp_ratio_dbytes = 0; break; #endif /* CONFIG_KLIPS_IPCOMP */ default: printk(KERN_ERR "KLIPS sa initialization: " "proto=%d unknown.\n", ipsp->ips_said.proto); SENDERR(EINVAL); } errlab: return(error); }
int pfkey_address_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) { int error = 0; int saddr_len = 0; char ipaddr_txt[ADDRTOA_BUF]; unsigned char **sap; unsigned short * portp = 0; struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext; struct sockaddr* s = (struct sockaddr*)((char*)pfkey_address + sizeof(*pfkey_address)); struct ipsec_sa* ipsp; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process:\n"); if(!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "extr or extr->ips is NULL, fatal\n"); SENDERR(EINVAL); } switch(s->sa_family) { case AF_INET: saddr_len = sizeof(struct sockaddr_in); addrtoa(((struct sockaddr_in*)s)->sin_addr, 0, ipaddr_txt, sizeof(ipaddr_txt)); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found address family=%d, AF_INET, %s.\n", s->sa_family, ipaddr_txt); break; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: saddr_len = sizeof(struct sockaddr_in6); break; #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ default: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "s->sa_family=%d not supported.\n", s->sa_family); SENDERR(EPFNOSUPPORT); } switch(pfkey_address->sadb_address_exttype) { case SADB_EXT_ADDRESS_SRC: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found src address.\n"); sap = (unsigned char **)&(extr->ips->ips_addr_s); extr->ips->ips_addr_s_size = saddr_len; break; case SADB_EXT_ADDRESS_DST: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found dst address.\n"); sap = (unsigned char **)&(extr->ips->ips_addr_d); extr->ips->ips_addr_d_size = saddr_len; break; case SADB_EXT_ADDRESS_PROXY: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found proxy address.\n"); sap = (unsigned char **)&(extr->ips->ips_addr_p); extr->ips->ips_addr_p_size = saddr_len; break; case SADB_X_EXT_ADDRESS_DST2: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found 2nd dst address.\n"); if(extr->ips2 == NULL) { extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */ } if(extr->ips2 == NULL) { SENDERR(-error); } sap = (unsigned char **)&(extr->ips2->ips_addr_d); extr->ips2->ips_addr_d_size = saddr_len; break; case SADB_X_EXT_ADDRESS_SRC_FLOW: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found src flow address.\n"); if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) { SENDERR(ENOMEM); } sap = (unsigned char **)&(extr->eroute->er_eaddr.sen_ip_src); portp = &(extr->eroute->er_eaddr.sen_sport); break; case SADB_X_EXT_ADDRESS_DST_FLOW: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found dst flow address.\n"); if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) { SENDERR(ENOMEM); } sap = (unsigned char **)&(extr->eroute->er_eaddr.sen_ip_dst); portp = &(extr->eroute->er_eaddr.sen_dport); break; case SADB_X_EXT_ADDRESS_SRC_MASK: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found src mask address.\n"); if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) { SENDERR(ENOMEM); } sap = (unsigned char **)&(extr->eroute->er_emask.sen_ip_src); portp = &(extr->eroute->er_emask.sen_sport); break; case SADB_X_EXT_ADDRESS_DST_MASK: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found dst mask address.\n"); if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) { SENDERR(ENOMEM); } sap = (unsigned char **)&(extr->eroute->er_emask.sen_ip_dst); portp = &(extr->eroute->er_emask.sen_dport); break; #ifdef NAT_TRAVERSAL case SADB_X_EXT_NAT_T_OA: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found NAT-OA address.\n"); sap = (unsigned char **)&(extr->ips->ips_natt_oa); extr->ips->ips_natt_oa_size = saddr_len; break; #endif default: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "unrecognised ext_type=%d.\n", pfkey_address->sadb_address_exttype); SENDERR(EINVAL); } switch(pfkey_address->sadb_address_exttype) { case SADB_EXT_ADDRESS_SRC: case SADB_EXT_ADDRESS_DST: case SADB_EXT_ADDRESS_PROXY: case SADB_X_EXT_ADDRESS_DST2: #ifdef NAT_TRAVERSAL case SADB_X_EXT_NAT_T_OA: #endif KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "allocating %d bytes for saddr.\n", saddr_len); if(!(*sap = kmalloc(saddr_len, GFP_KERNEL))) { SENDERR(ENOMEM); } memcpy(*sap, s, saddr_len); break; default: if(s->sa_family != AF_INET) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "s->sa_family=%d not supported.\n", s->sa_family); SENDERR(EPFNOSUPPORT); } { unsigned long *ulsap = (unsigned long *)sap; *ulsap = ((struct sockaddr_in*)s)->sin_addr.s_addr; } if (portp != 0) *portp = ((struct sockaddr_in*)s)->sin_port; #ifdef CONFIG_KLIPS_DEBUG if(extr->eroute) { char buf1[64], buf2[64]; if (debug_pfkey) { subnettoa(extr->eroute->er_eaddr.sen_ip_src, extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1)); subnettoa(extr->eroute->er_eaddr.sen_ip_dst, extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2)); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_parse: " "extr->eroute set to %s:%d->%s:%d\n", buf1, ntohs(extr->eroute->er_eaddr.sen_sport), buf2, ntohs(extr->eroute->er_eaddr.sen_dport)); } } #endif /* CONFIG_KLIPS_DEBUG */ } ipsp = extr->ips; switch(pfkey_address->sadb_address_exttype) { case SADB_X_EXT_ADDRESS_DST2: ipsp = extr->ips2; case SADB_EXT_ADDRESS_DST: if(s->sa_family == AF_INET) { ipsp->ips_said.dst.u.v4.sin_addr.s_addr = ((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr.s_addr; ipsp->ips_said.dst.u.v4.sin_family = AF_INET; addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr, 0, ipaddr_txt, sizeof(ipaddr_txt)); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "ips_said.dst set to %s.\n", ipaddr_txt); } else { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "uh, ips_said.dst doesn't do address family=%d yet, said will be invalid.\n", s->sa_family); } default: break; } /* XXX check if port!=0 */ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: successful.\n"); errlab: return error; }