When using AH, all "mutable" fields must be "zeroed" before calculating the ICV. See RFC 4302, Section 3.3.3.1. Handling Mutable Fields. :param pkt: an IP(v6) packet containing an AH layer. NOTE: The packet will be modified :param sending: if true, ipv6 routing head
(pkt, sending=False)
| 855 | |
| 856 | |
| 857 | def zero_mutable_fields(pkt, sending=False): |
| 858 | """ |
| 859 | When using AH, all "mutable" fields must be "zeroed" before calculating |
| 860 | the ICV. See RFC 4302, Section 3.3.3.1. Handling Mutable Fields. |
| 861 | |
| 862 | :param pkt: an IP(v6) packet containing an AH layer. |
| 863 | NOTE: The packet will be modified |
| 864 | :param sending: if true, ipv6 routing headers will not be reordered |
| 865 | """ |
| 866 | |
| 867 | if pkt.haslayer(AH): |
| 868 | pkt[AH].icv = b"\x00" * len(pkt[AH].icv) |
| 869 | else: |
| 870 | raise TypeError('no AH layer found') |
| 871 | |
| 872 | if pkt.version == 4: |
| 873 | # the tos field has been replaced by DSCP and ECN |
| 874 | # Routers may rewrite the DS field as needed to provide a |
| 875 | # desired local or end-to-end service |
| 876 | pkt.tos = 0 |
| 877 | # an intermediate router might set the DF bit, even if the source |
| 878 | # did not select it. |
| 879 | pkt.flags = 0 |
| 880 | # changed en route as a normal course of processing by routers |
| 881 | pkt.ttl = 0 |
| 882 | # will change if any of these other fields change |
| 883 | pkt.chksum = 0 |
| 884 | |
| 885 | immutable_opts = [] |
| 886 | for opt in pkt.options: |
| 887 | if opt.option in IMMUTABLE_IPV4_OPTIONS: |
| 888 | immutable_opts.append(opt) |
| 889 | else: |
| 890 | immutable_opts.append(Raw(b"\x00" * len(opt))) |
| 891 | pkt.options = immutable_opts |
| 892 | |
| 893 | else: |
| 894 | # holds DSCP and ECN |
| 895 | pkt.tc = 0 |
| 896 | # The flow label described in AHv1 was mutable, and in RFC 2460 [DH98] |
| 897 | # was potentially mutable. To retain compatibility with existing AH |
| 898 | # implementations, the flow label is not included in the ICV in AHv2. |
| 899 | pkt.fl = 0 |
| 900 | # same as ttl |
| 901 | pkt.hlim = 0 |
| 902 | |
| 903 | next_hdr = pkt.payload |
| 904 | |
| 905 | while isinstance(next_hdr, (IPv6ExtHdrHopByHop, IPv6ExtHdrRouting, IPv6ExtHdrDestOpt)): # noqa: E501 |
| 906 | if isinstance(next_hdr, (IPv6ExtHdrHopByHop, IPv6ExtHdrDestOpt)): |
| 907 | for opt in next_hdr.options: |
| 908 | if opt.otype & 0x20: |
| 909 | # option data can change en-route and must be zeroed |
| 910 | opt.optdata = b"\x00" * opt.optlen |
| 911 | elif isinstance(next_hdr, IPv6ExtHdrRouting) and sending: |
| 912 | # The sender must order the field so that it appears as it |
| 913 | # will at the receiver, prior to performing the ICV computation. # noqa: E501 |
| 914 | next_hdr.segleft = 0 |