예제 #1
0
파일: fpp.py 프로젝트: ccie18643/PyTCP
    def _packet_integrity_check(self) -> str:
        """Packet integrity check to be run on raw packet prior to parsing to make sure parsing is safe"""

        if not config.PACKET_INTEGRITY_CHECK:
            return ""

        if len(self) < IP4_HEADER_LEN:
            return "IPv4 integrity - wrong packet length (I)"

        if not IP4_HEADER_LEN <= self.hlen <= self.plen <= len(self):
            return "IPv4 integrity - wrong packet length (II)"

        # Cannot compute checksum earlier because it depends on sanity of hlen field
        if inet_cksum(self._frame[:self.hlen]):
            return "IPv4 integriy - wrong packet checksum"

        optr = IP4_HEADER_LEN
        while optr < self.hlen:
            if self._frame[optr] == IP4_OPT_EOL:
                break
            if self._frame[optr] == IP4_OPT_NOP:
                optr += 1
                if optr > self.hlen:
                    return "IPv4 integrity - wrong option length (I)"
                continue
            if optr + 1 > self.hlen:
                return "IPv4 integrity - wrong option length (II)"
            if self._frame[optr + 1] == 0:
                return "IPv4 integrity - wrong option length (III)"
            optr += self._frame[optr + 1]
            if optr > self.hlen:
                return "IPv4 integrity - wrong option length (IV)"

        return ""
예제 #2
0
파일: fpp.py 프로젝트: ccie18643/PyTCP
    def _packet_integrity_check(self, pshdr_sum: int) -> str:
        """Packet integrity check to be run on raw frame prior to parsing to make sure parsing is safe"""

        if not config.PACKET_INTEGRITY_CHECK:
            return ""

        if inet_cksum(self._frame[: self._plen], pshdr_sum):
            return "TCP integrity - wrong packet checksum"

        if not TCP_HEADER_LEN <= self._plen <= len(self):
            return "TCP integrity - wrong packet length (I)"

        hlen = (self._frame[12] & 0b11110000) >> 2
        if not TCP_HEADER_LEN <= hlen <= self._plen <= len(self):
            return "TCP integrity - wrong packet length (II)"

        optr = TCP_HEADER_LEN
        while optr < hlen:
            if self._frame[optr] == TCP_OPT_EOL:
                break
            if self._frame[optr] == TCP_OPT_NOP:
                optr += 1
                if optr > hlen:
                    return "TCP integrity - wrong option length (I)"
                continue
            if optr + 1 > hlen:
                return "TCP integrity - wrong option length (II)"
            if self._frame[optr + 1] == 0:
                return "TCP integrity - wrong option length (III)"
            optr += self._frame[optr + 1]
            if optr > hlen:
                return "TCP integrity - wrong option length (IV)"

        return ""
예제 #3
0
파일: fpp.py 프로젝트: ccie18643/PyTCP
    def _packet_integrity_check(self, pshdr_sum: int) -> str:
        """Packet integrity check to be run on raw frame prior to parsing to make sure parsing is safe"""

        if not config.PACKET_INTEGRITY_CHECK:
            return ""

        if inet_cksum(self._frame[:self._plen], pshdr_sum):
            return "ICMPv6 integrity - wrong packet checksum"

        if not ICMP6_HEADER_LEN <= self._plen <= len(self):
            return "ICMPv6 integrity - wrong packet length (I)"

        if self._frame[0] == ICMP6_UNREACHABLE:
            if not 12 <= self._plen <= len(self):
                return "ICMPv6 integrity - wrong packet length (II)"

        elif self._frame[0] in {ICMP6_ECHO_REQUEST, ICMP6_ECHO_REPLY}:
            if not 8 <= self._plen <= len(self):
                return "ICMPv6 integrity - wrong packet length (II)"

        elif self._frame[0] == ICMP6_MLD2_QUERY:
            if not 28 <= self._plen <= len(self):
                return "ICMPv6 integrity - wrong packet length (II)"
            if self._plen != 28 + struct.unpack("!H",
                                                self._frame[26:28])[0] * 16:
                return "ICMPv6 integrity - wrong packet length (III)"

        elif self._frame[0] == ICMP6_ROUTER_SOLICITATION:
            if not 8 <= self._plen <= len(self):
                return "ICMPv6 integrity - wrong packet length (II)"
            if fail := self._nd_option_integrity_check(8):
                return fail
예제 #4
0
파일: fpa.py 프로젝트: ccie18643/PyTCP
    def assemble(self, frame: memoryview, pshdr_sum: int) -> None:
        """Assemble packet into the raw form"""

        struct.pack_into(
            f"! HH L L BBH HH {len(self._raw_options)}s {len(self._data)}s",
            frame,
            0,
            self._sport,
            self._dport,
            self._seq,
            self._ack,
            self._hlen << 2 | self._flag_ns,
            self._flag_crw << 7
            | self._flag_ece << 6
            | self._flag_urg << 5
            | self._flag_ack << 4
            | self._flag_psh << 3
            | self._flag_rst << 2
            | self._flag_syn << 1
            | self._flag_fin,
            self._win,
            0,
            self._urp,
            self._raw_options,
            self._data,
        )

        struct.pack_into("! H", frame, 16, inet_cksum(frame, pshdr_sum))
예제 #5
0
    def _packet_integrity_check(self, pshdr_sum: int) -> str:
        """Packet integrity check to be run on raw frame prior to parsing to make sure parsing is safe"""

        if not config.PACKET_INTEGRITY_CHECK:
            return ""

        if inet_cksum(self._frame[:self._plen], pshdr_sum):
            return "UDP integrity - wrong packet checksum"

        if not UDP_HEADER_LEN <= self._plen <= len(self):
            return "UDP integrity - wrong packet length (I)"

        plen = struct.unpack("!H", self._frame[4:6])[0]
        if not UDP_HEADER_LEN <= plen == self._plen <= len(self):
            return "UDP integrity - wrong packet length (II)"

        return ""
예제 #6
0
파일: fpp.py 프로젝트: ccie18643/PyTCP
    def _packet_integrity_check(self) -> str:
        """Packet integrity check to be run on raw frame prior to parsing to make sure parsing is safe"""

        if not config.PACKET_INTEGRITY_CHECK:
            return ""

        if inet_cksum(self._frame[:self._plen]):
            return "ICMPv4 integrity - wrong packet checksum"

        if not ICMP4_HEADER_LEN <= self._plen <= len(self):
            return "ICMPv4 integrity - wrong packet length (I)"

        if self._frame[0] in {ICMP4_ECHO_REQUEST, ICMP4_ECHO_REPLY}:
            if not 8 <= self._plen <= len(self):
                return "ICMPv6 integrity - wrong packet length (II)"

        elif self._frame[0] == ICMP4_UNREACHABLE:
            if not 12 <= self._plen <= len(self):
                return "ICMPv6 integrity - wrong packet length (II)"

        return ""
예제 #7
0
    def assemble(self, frame: memoryview) -> None:
        """Assemble packet into the raw form"""

        struct.pack_into(
            f"! BBH HH BBH 4s 4s {len(self._raw_options)}s {len(self._data)}s",
            frame,
            0,
            self._ver << 4 | self._hlen >> 2,
            self._dscp << 2 | self._ecn,
            self._plen,
            self._id,
            self._flag_df << 14 | self._flag_mf << 13 | self._offset >> 3,
            self._ttl,
            self._proto,
            0,
            bytes(self._src),
            bytes(self._dst),
            bytes(self._raw_options),  # memoryview: conversion to bytes requir
            bytes(self._data),  # memoryview: conversion to bytes requir
        )

        struct.pack_into("! H", frame, 10, inet_cksum(frame[:self._hlen]))
예제 #8
0
파일: fpa.py 프로젝트: ccie18643/PyTCP
    def assemble(self, frame: memoryview, _: int = 0) -> None:
        """Assemble packet into the raw form"""

        if self._type == ICMP4_ECHO_REPLY:
            # memoryview: bytes conversion required
            struct.pack_into(f"! BBH HH {len(self._ec_data)}s", frame, 0,
                             self._type, self._code, 0, self._ec_id,
                             self._ec_seq, bytes(self._ec_data))

        elif self._type == ICMP4_UNREACHABLE and self._code == ICMP4_UNREACHABLE__PORT:
            # memoryview: bytes conversion required
            struct.pack_into(f"! BBH L {len(self._un_data)}s", frame,
                             0, self._type, self._code, 0, 0,
                             bytes(self._un_data))

        elif self._type == ICMP4_ECHO_REQUEST:
            # memoryview: bytes conversion required
            struct.pack_into(f"! BBH HH {len(self._ec_data)}s", frame, 0,
                             self._type, self._code, 0, self._ec_id,
                             self._ec_seq, bytes(self._ec_data))

        struct.pack_into("! H", frame, 2, inet_cksum(frame))
예제 #9
0
    def assemble(self, frame: memoryview) -> None:
        """Assemble packet into the raw form"""

        struct.pack_into(
            f"! BBH HH BBH 4s 4s {len(self._raw_options)}s",
            frame,
            0,
            self._ver << 4 | self._hlen >> 2,
            self._dscp << 2 | self._ecn,
            self._plen,
            self._id,
            self._flag_df << 14 | self._flag_mf << 13 | self._offset >> 3,
            self._ttl,
            self._proto,
            0,
            bytes(self._src),
            bytes(self._dst),
            self._raw_options,
        )

        struct.pack_into("! H", frame, 10, inet_cksum(frame[:self._hlen]))

        self._carried_packet.assemble(frame[self._hlen:], self.pshdr_sum)
예제 #10
0
    def assemble(self, frame: memoryview, pshdr_sum: int) -> None:
        """Assemble packet into the raw form"""

        # memoryview: bytes conversion requir
        struct.pack_into(f"! HH HH {len(self._data)}s", frame, 0, self._sport, self._dport, self._plen, 0, bytes(self._data))
        struct.pack_into("! H", frame, 6, inet_cksum(frame, pshdr_sum))
예제 #11
0
파일: phrx.py 프로젝트: ccie18643/PyTCP
def _defragment_ip4_packet(self, packet_rx: PacketRx) -> Optional[PacketRx]:
    """Defragment IPv4 packet"""

    # Cleanup expir flows
    self.ip4_frag_flows = {
        _: self.ip4_frag_flows[_]
        for _ in self.ip4_frag_flows if self.ip4_frag_flows[_]["timestamp"] -
        time() < config.IP4_FRAG_FLOW_TIMEOUT
    }

    if __debug__:
        log(
            "ip4",
            f"{packet_rx.tracker} - IPv4 packet fragment, offset {packet_rx.ip4.offset}, dlen {packet_rx.ip4.dlen}"
            + f"{'' if packet_rx.ip4.flag_mf else ', last'}",
        )

    flow_id = (packet_rx.ip4.src, packet_rx.ip4.dst, packet_rx.ip4.id)

    # Update flow db
    if self.ip4_frag_flows.get(flow_id, None):
        self.ip4_frag_flows[flow_id]["data"][
            packet_rx.ip4.offset] = packet_rx.ip4.data_copy
    else:
        self.ip4_frag_flows[flow_id] = {
            "header": packet_rx.ip4.header_copy,
            "timestamp": time(),
            "last": False,
            "data": {
                packet_rx.ip4.offset: packet_rx.ip4.data_copy
            },
        }
    if not packet_rx.ip4.flag_mf:
        self.ip4_frag_flows[flow_id]["last"] = True

    # Test if we received all fragments
    if not self.ip4_frag_flows[flow_id]["last"]:
        return None
    data_len = 0
    for offset in sorted(self.ip4_frag_flows[flow_id]["data"]):
        if offset > data_len:
            return None
        data_len = offset + len(self.ip4_frag_flows[flow_id]["data"][offset])

    # Defragment packet
    header = bytearray(self.ip4_frag_flows[flow_id]["header"])
    data = bytearray(data_len)
    for offset in sorted(self.ip4_frag_flows[flow_id]["data"]):
        struct.pack_into(
            f"{len(self.ip4_frag_flows[flow_id]['data'][offset])}s", data,
            offset, self.ip4_frag_flows[flow_id]["data"][offset])
    del self.ip4_frag_flows[flow_id]
    header[0] = 0x45
    struct.pack_into("!H", header, 2, IP4_HEADER_LEN + len(data))
    header[6] = header[7] = header[10] = header[11] = 0
    struct.pack_into("!H", header, 10, inet_cksum(memoryview(header)))
    packet_rx = PacketRx(bytes(header) + data)
    Ip4Parser(packet_rx)
    if __debug__:
        log(
            "ip4",
            f"{packet_rx.tracker} - Reasembled fragmented IPv4 packet, dlen {len(data)} bytes"
        )
    return packet_rx
예제 #12
0
    def assemble(self, frame: memoryview, pshdr_sum: int) -> None:
        """Assemble packet into the raw form"""

        if self._type == ICMP6_UNREACHABLE:
            struct.pack_into(f"! BBH L {len(self._un_data)}s", frame, 0,
                             self._type, self._code, 0, self._un_reserved,
                             self._un_data)

        elif self._type == ICMP6_ECHO_REQUEST:
            struct.pack_into(f"! BBH HH {len(self._ec_data)}s", frame, 0,
                             self._type, self._code, 0, self._ec_id,
                             self._ec_seq, self._ec_data)

        elif self._type == ICMP6_ECHO_REPLY:
            # memoryview: bytes conversion required
            struct.pack_into(f"! BBH HH {len(self._ec_data)}s", frame, 0,
                             self._type, self._code, 0, self._ec_id,
                             self._ec_seq, bytes(self._ec_data))

        elif self._type == ICMP6_ROUTER_SOLICITATION:
            struct.pack_into(f"! BBH L {len(self._raw_nd_options)}s", frame, 0,
                             self._type, self._code, 0, self._rs_reserved,
                             self._raw_nd_options)

        elif self._type == ICMP6_ROUTER_ADVERTISEMENT:
            assert self._ra_flag_m is not None
            assert self._ra_flag_o is not None
            struct.pack_into(
                f"! BBH BBH L L {len(self._raw_nd_options)}s",
                frame,
                0,
                self._type,
                self._code,
                0,
                self._ra_hop,
                (self._ra_flag_m << 7) | (self._ra_flag_o << 6),
                self._ra_router_lifetime,
                self._ra_reachable_time,
                self._ra_retrans_timer,
                self._raw_nd_options,
            )

        elif self._type == ICMP6_NEIGHBOR_SOLICITATION:
            assert self._ns_target_address is not None
            struct.pack_into(
                f"! BBH L 16s {len(self._raw_nd_options)}s",
                frame,
                0,
                self._type,
                self._code,
                0,
                self._ns_reserved,
                bytes(self._ns_target_address),
                self._raw_nd_options,
            )

        elif self._type == ICMP6_NEIGHBOR_ADVERTISEMENT:
            assert self._na_flag_r is not None
            assert self._na_flag_s is not None
            assert self._na_flag_o is not None
            assert self._na_target_address is not None
            struct.pack_into(
                f"! BBH L 16s {len(self._raw_nd_options)}s",
                frame,
                0,
                self._type,
                self._code,
                0,
                (self._na_flag_r << 31) | (self._na_flag_s << 30) |
                (self._na_flag_o << 29) | self._na_reserved,
                bytes(self._na_target_address),
                self._raw_nd_options,
            )

        elif self._type == ICMP6_MLD2_REPORT:
            struct.pack_into(
                f"! BBH HH {sum([len(_) for _ in self._mlr2_multicast_address_record])}s",
                frame,
                0,
                self._type,
                self._code,
                0,
                self._mlr2_reserved,
                self._mlr2_number_of_multicast_address_records,
                b"".join([
                    _.raw_record for _ in self._mlr2_multicast_address_record
                ]),
            )

        struct.pack_into("! H", frame, 2, inet_cksum(frame, pshdr_sum))