Merge pull request #1067 from gpotter2/win-static-py3
Static access to LOOPBACK_INTERFACE
diff --git a/.coveragerc b/.coveragerc
index cec0a08..e279ef3 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -1,5 +1,7 @@
[run]
omit =
+ # Travis specific path
+ /home/travis/virtualenv/python*
# Python specific path
/usr/local/lib/python2.7/*
# Scapy specific paths
@@ -8,6 +10,4 @@
scapy/tools/*
# Libraries
scapy/modules/six.py
- scapy/modules/winpcapy.py
- # Python 3: not tested yet
- scapy/compat.py
+ scapy/modules/winpcapy.py
diff --git a/.travis/test.sh b/.travis/test.sh
index 9e239cf..46c1ef4 100644
--- a/.travis/test.sh
+++ b/.travis/test.sh
@@ -71,7 +71,7 @@
then
echo '#!/bin/bash' > test/python
echo "[ \"\$*\" = \"--version\" ] && echo \"`python --version`\" && exit 0" >> test/python
- echo "`which coverage` run --concurrency=multiprocessing -a \$*" >> test/python
+ echo "`which coverage` run --rcfile=../.coveragerc --concurrency=multiprocessing -a \$*" >> test/python
chmod +x test/python
# Copy the fake Python interpreter to bypass /etc/sudoers rules on Ubuntu
diff --git a/README.md b/README.md
index 557b0f3..8f4963c 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@
using default values that work.
It can easily handle most classical tasks like scanning, tracerouting, probing,
-unit tests, attacks or network discovery (it can replace `hping`, 85% of `nmap̀`,
+unit tests, attacks or network discovery (it can replace `hping`, 85% of `nmap`,
`arpspoof`, `arp-sk`, `arping`, `tcpdump`, `wireshark`, `p0f`, etc.). It also
performs very well at a lot of other specific tasks that most other tools can't
handle, like sending invalid frames, injecting your own 802.11 frames, combining
@@ -66,7 +66,7 @@
p = IP(dst="github.com")/TCP()
r = sr1(p)
-print r.summary()
+print(r.summary())
```
Then, launch the script with:
diff --git a/scapy/arch/bpf/core.py b/scapy/arch/bpf/core.py
index 0340fa6..040067b 100644
--- a/scapy/arch/bpf/core.py
+++ b/scapy/arch/bpf/core.py
@@ -173,7 +173,7 @@
# Check if the interface can be used
try:
- fcntl.ioctl(fd, BIOCSETIF, struct.pack("16s16x", ifname))
+ fcntl.ioctl(fd, BIOCSETIF, struct.pack("16s16x", ifname.encode()))
interfaces.append((ifname, int(ifname[-1])))
except IOError as err:
pass
diff --git a/scapy/arch/bpf/supersocket.py b/scapy/arch/bpf/supersocket.py
index 34c8f15..7d04e18 100644
--- a/scapy/arch/bpf/supersocket.py
+++ b/scapy/arch/bpf/supersocket.py
@@ -66,7 +66,7 @@
# Assign the network interface to the BPF handle
try:
- fcntl.ioctl(self.ins, BIOCSETIF, struct.pack("16s16x", self.iface))
+ fcntl.ioctl(self.ins, BIOCSETIF, struct.pack("16s16x", self.iface.encode()))
except IOError:
raise Scapy_Exception("BIOCSETIF failed on %s" % self.iface)
self.assigned_interface = self.iface
@@ -324,7 +324,7 @@
# Assign the network interface to the BPF handle
if self.assigned_interface != iff:
try:
- fcntl.ioctl(self.outs, BIOCSETIF, struct.pack("16s16x", iff))
+ fcntl.ioctl(self.outs, BIOCSETIF, struct.pack("16s16x", iff.encode()))
except IOError:
raise Scapy_Exception("BIOCSETIF failed on %s" % iff)
self.assigned_interface = iff
diff --git a/scapy/arch/windows/__init__.py b/scapy/arch/windows/__init__.py
index 6641970..abb1ea7 100755
--- a/scapy/arch/windows/__init__.py
+++ b/scapy/arch/windows/__init__.py
@@ -521,7 +521,8 @@
Only available with Npcap."""
# According to https://nmap.org/npcap/guide/npcap-devguide.html#npcap-feature-dot11
self._check_npcap_requirement()
- return sp.Popen([_WlanHelper, self.guid[1:-1], "channel"], stdout=sp.PIPE).communicate()[0].strip().strip()
+ return sp.Popen([_WlanHelper, self.guid[1:-1], "channel"],
+ stdout=sp.PIPE).communicate()[0].strip()
def setchannel(self, channel):
"""Set the channel of the interface (1-14):
@@ -853,14 +854,13 @@
_buffer = []
_pattern = re.compile(".*:\s+(\d+)")
for _line in stdout:
- if not _line.strip():
- continue
- _buffer.append(_line)
- if len(_buffer) == 32: # An interface, with all its parameters, is 32 lines long
+ if not _line.strip() and len(_buffer) > 0:
if_index = re.search(_pattern, _buffer[3]).group(1)
if_metric = int(re.search(_pattern, _buffer[5]).group(1))
res[if_index] = if_metric
_buffer = []
+ else:
+ _buffer.append(_line)
return res
def _read_routes_post2008():
diff --git a/scapy/base_classes.py b/scapy/base_classes.py
index a269796..85c47f5 100644
--- a/scapy/base_classes.py
+++ b/scapy/base_classes.py
@@ -166,7 +166,7 @@
resolved_fld.append(f2)
else:
resolved_fld.append(f)
- else: # look for a field_desc in parent classes
+ else: # look for a fields_desc in parent classes
resolved_fld = None
for b in bases:
if hasattr(b,"fields_desc"):
diff --git a/scapy/compat.py b/scapy/compat.py
index 1737c04..d00029a 100644
--- a/scapy/compat.py
+++ b/scapy/compat.py
@@ -77,7 +77,7 @@
def plain_str(x):
"""Convert basic byte objects to str"""
- return x
+ return x if isinstance(x, basestring) else str(x)
def chb(x):
"""Same than chr() but encode as bytes.
@@ -101,7 +101,7 @@
"""Convert basic byte objects to str"""
if isinstance(x, bytes):
return x.decode('utf8')
- return x
+ return x if isinstance(x, str) else str(x)
def chb(x):
"""Same than chr() but encode as bytes.
diff --git a/scapy/data.py b/scapy/data.py
index ff06438..71dda32 100644
--- a/scapy/data.py
+++ b/scapy/data.py
@@ -87,6 +87,7 @@
DLT_IEEE802_11_RADIO = 127
DLT_LINUX_IRDA = 144
DLT_PPI = 192
+DLT_CAN_SOCKETCAN = 227
DLT_IPV4 = 228
DLT_IPV6 = 229
diff --git a/scapy/layers/can.py b/scapy/layers/can.py
new file mode 100644
index 0000000..7dc2d33
--- /dev/null
+++ b/scapy/layers/can.py
@@ -0,0 +1,36 @@
+# This file is part of Scapy
+# See http://www.secdev.org/projects/scapy for more informations
+# Copyright (C) Philippe Biondi <phil@secdev.org>
+# This program is published under a GPLv2 license
+
+
+"""A minimal implementation of the CANopen protocol, based on
+Wireshark dissectors. See https://wiki.wireshark.org/CANopen
+
+"""
+
+
+from scapy.config import conf
+from scapy.data import DLT_CAN_SOCKETCAN
+from scapy.fields import BitField, FieldLenField, FlagsField, StrLenField, \
+ ThreeBytesField, XBitField
+from scapy.packet import Packet
+
+
+class CAN(Packet):
+ """A minimal implementation of the CANopen protocol, based on
+ Wireshark dissectors. See https://wiki.wireshark.org/CANopen
+
+ """
+ fields_desc = [
+ FlagsField("flags", 0, 3, ["extended", "remote_transmission_request",
+ "error"]),
+ BitField("unknown", 0, 18),
+ XBitField("identifier", 0, 11),
+ FieldLenField("length", None, length_of="data", fmt="B"),
+ ThreeBytesField("reserved", 0),
+ StrLenField("data", "", length_from=lambda pkt: pkt.length),
+ ]
+
+
+conf.l2types.register(DLT_CAN_SOCKETCAN, CAN)
diff --git a/scapy/layers/radius.py b/scapy/layers/radius.py
index ada1cb4..be7b549 100644
--- a/scapy/layers/radius.py
+++ b/scapy/layers/radius.py
@@ -10,6 +10,8 @@
import struct
import logging
+import hashlib
+import hmac
from scapy.compat import *
from scapy.packet import Packet, bind_layers
from scapy.fields import ByteField, ByteEnumField, IntField, StrLenField,\
@@ -21,20 +23,6 @@
from scapy.error import Scapy_Exception
-g_log_loading = logging.getLogger("scapy.logging")
-
-_crypto_loading_failure_message = \
- "Could not import python-cryptography."\
- "Computations for the \"authenticator\" field (RADIUS packets) and"\
- "\"Message-Authenticator\" attribute value field are disabled."
-
-if conf.crypto_valid:
- from cryptography.hazmat.backends import default_backend
- from cryptography.hazmat.primitives import hashes, hmac
-else:
- g_log_loading.info(_crypto_loading_failure_message)
-
-
# https://www.iana.org/assignments/radius-types/radius-types.xhtml
_radius_attribute_types = {
1: "User-Name",
@@ -540,6 +528,23 @@
val = 24
+
+def prepare_packed_data(radius_packet, packed_req_authenticator):
+ """
+ Pack RADIUS data prior computing the authentication MAC
+ """
+
+ packed_hdr = struct.pack("!B", radius_packet.code)
+ packed_hdr += struct.pack("!B", radius_packet.id)
+ packed_hdr += struct.pack("!H", radius_packet.len)
+
+ packed_attrs = b''
+ for attr in radius_packet.attributes:
+ packed_attrs += raw(attr)
+
+ return packed_hdr + packed_req_authenticator + packed_attrs
+
+
class RadiusAttr_Message_Authenticator(_RadiusAttrHexStringVal):
"""RFC 2869"""
val = 80
@@ -556,35 +561,16 @@
]
@staticmethod
- def compute_message_authenticator(
- radius_packet,
- packed_req_authenticator,
- shared_secret
- ):
+ def compute_message_authenticator(radius_packet, packed_req_authenticator,
+ shared_secret):
"""
Computes the "Message-Authenticator" of a given RADIUS packet.
"""
- if not conf.crypto_valid:
- g_log_loading.info(_crypto_loading_failure_message)
- return None
+ data = prepare_packed_data(radius_packet, packed_req_authenticator)
+ radius_hmac = hmac.new(shared_secret, data, hashlib.md5)
- packed_hdr = struct.pack("!B", radius_packet.code)
- packed_hdr += struct.pack("!B", radius_packet.id)
- packed_hdr += struct.pack("!H", radius_packet.len)
- packed_attrs = ''
- for index in range(0, len(radius_packet.attributes)):
- packed_attrs = packed_attrs + str(radius_packet.attributes[index])
-
- hmac_ = hmac.HMAC(
- shared_secret,
- hashes.MD5(),
- backend=default_backend()
- )
- packed_data = packed_hdr + packed_req_authenticator + packed_attrs
- hmac_.update(packed_data)
- return hmac_.finalize()
-
+ return radius_hmac.digest()
#
# RADIUS attributes which values are IPv4 prefixes
@@ -1171,23 +1157,9 @@
Computes the authenticator field (RFC 2865 - Section 3)
"""
- if not conf.crypto_valid:
- g_log_loading.info(_crypto_loading_failure_message)
- return None
-
- packed_hdr = struct.pack("!B", self.code)
- packed_hdr += struct.pack("!B", self.id)
- packed_hdr += struct.pack("!H", self.len)
- packed_attrs = b''
- for attr in self.attributes:
- packed_attrs = packed_attrs + raw(attr)
- packed_data = packed_hdr + packed_request_auth + packed_attrs +\
- shared_secret
-
- digest = hashes.Hash(hashes.MD5(), backend=default_backend())
- digest.update(packed_data)
- return digest.finalize()
-
+ data = prepare_packed_data(self, packed_request_auth)
+ radius_mac = hashlib.md5(data + shared_secret)
+ return radius_mac.digest()
def post_build(self, p, pay):
p += pay
diff --git a/scapy/layers/tls/automaton.py b/scapy/layers/tls/automaton.py
index c9f2329..886b1b2 100644
--- a/scapy/layers/tls/automaton.py
+++ b/scapy/layers/tls/automaton.py
@@ -130,6 +130,7 @@
else:
self.remain_in += tmp
except:
+ self.vprint("Could not join host ! Retrying...")
retry -= 1
if len(self.remain_in) < 2 or len(self.remain_in) != grablen:
diff --git a/scapy/layers/tls/automaton_cli.py b/scapy/layers/tls/automaton_cli.py
index d58a6b2..bda49df 100644
--- a/scapy/layers/tls/automaton_cli.py
+++ b/scapy/layers/tls/automaton_cli.py
@@ -20,6 +20,7 @@
from __future__ import print_function
import socket
+from scapy.pton_ntop import inet_pton
from scapy.utils import randstring
from scapy.automaton import ATMT
from scapy.layers.tls.automaton import _TLSAutomaton
@@ -70,9 +71,9 @@
self.remote_name = None
try:
if ':' in server:
- socket.inet_pton(socket.AF_INET6, server)
+ inet_pton(socket.AF_INET6, server)
else:
- socket.inet_pton(socket.AF_INET, server)
+ inet_pton(socket.AF_INET, server)
except:
self.remote_name = socket.getfqdn(server)
if self.remote_name != server:
diff --git a/scapy/layers/tls/automaton_srv.py b/scapy/layers/tls/automaton_srv.py
index 9f76df4..1d37aa4 100644
--- a/scapy/layers/tls/automaton_srv.py
+++ b/scapy/layers/tls/automaton_srv.py
@@ -19,6 +19,7 @@
from __future__ import print_function
import socket
+from scapy.pton_ntop import inet_pton
from scapy.utils import randstring, repr_hex
from scapy.automaton import ATMT
from scapy.layers.tls.automaton import _TLSAutomaton
@@ -69,9 +70,9 @@
**kargs)
try:
if ':' in server:
- socket.inet_pton(socket.AF_INET6, server)
+ inet_pton(socket.AF_INET6, server)
else:
- socket.inet_pton(socket.AF_INET, server)
+ inet_pton(socket.AF_INET, server)
tmp = socket.getaddrinfo(server, sport)
except:
tmp = socket.getaddrinfo(socket.getfqdn(server), sport)
diff --git a/scapy/layers/tls/cert.py b/scapy/layers/tls/cert.py
index 735e63a..acd771a 100644
--- a/scapy/layers/tls/cert.py
+++ b/scapy/layers/tls/cert.py
@@ -279,9 +279,9 @@
def import_from_tuple(self, tup):
# this is rarely used
e, m, mLen = tup
- if isinstance(m, str):
+ if isinstance(m, bytes):
m = pkcs_os2ip(m)
- if isinstance(e, str):
+ if isinstance(e, bytes):
e = pkcs_os2ip(e)
self.fill_and_store(modulus=m, pubExp=e)
self.pem = self.pubkey.public_bytes(
@@ -512,7 +512,6 @@
@crypto_validator
def import_from_asn1pkt(self, privkey):
- print(privkey)
self.key = serialization.load_der_private_key(raw(privkey), None,
backend=default_backend())
self.pubkey = self.key.public_key()
diff --git a/scapy/layers/tls/crypto/cipher_block.py b/scapy/layers/tls/crypto/cipher_block.py
index bd2b04f..ab463cc 100644
--- a/scapy/layers/tls/crypto/cipher_block.py
+++ b/scapy/layers/tls/crypto/cipher_block.py
@@ -51,7 +51,7 @@
else:
l = self.key_len
key = b"\0" * l
- if iv is None or iv == "":
+ if not iv:
self.ready["iv"] = False
iv = b"\0" * self.block_size
diff --git a/scapy/layers/tls/crypto/groups.py b/scapy/layers/tls/crypto/groups.py
index 9cef2a3..f0a9ca3 100644
--- a/scapy/layers/tls/crypto/groups.py
+++ b/scapy/layers/tls/crypto/groups.py
@@ -68,8 +68,8 @@
return the_class
-class _FFDHParams(object):
- __metaclass__ = _FFDHParamsMetaclass
+class _FFDHParams(six.with_metaclass(_FFDHParamsMetaclass)):
+ pass
class modp768(_FFDHParams):
diff --git a/scapy/layers/tls/handshake.py b/scapy/layers/tls/handshake.py
index 4a4226a..95cd914 100644
--- a/scapy/layers/tls/handshake.py
+++ b/scapy/layers/tls/handshake.py
@@ -608,7 +608,7 @@
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt:
tls_session = kargs.get("tls_session", None)
- if tls_session and tls_session.tls_version >= 0x0304:
+ if tls_session and (tls_session.tls_version or 0) >= 0x0304:
return TLS13Certificate
return TLSCertificate
diff --git a/scapy/layers/tls/keyexchange.py b/scapy/layers/tls/keyexchange.py
index 386a9bb..64ed6be 100644
--- a/scapy/layers/tls/keyexchange.py
+++ b/scapy/layers/tls/keyexchange.py
@@ -120,7 +120,7 @@
s = pkt.tls_session
if s.tls_version and s.tls_version < 0x0300:
if len(s.client_certs) > 0:
- sig_len = s.client_certs[0].pubKey.pubkey.key_size / 8
+ sig_len = s.client_certs[0].pubKey.pubkey.key_size // 8
else:
warning("No client certificate provided. "
"We're making a wild guess about the signature size.")
@@ -219,7 +219,7 @@
i = self.m2i(pkt, s)
if i is None:
return s, None
- remain = ""
+ remain = b""
if conf.padding_layer in i:
r = i[conf.padding_layer]
del(r.underlayer.payload)
@@ -307,12 +307,12 @@
default_params = _ffdh_groups['modp2048'][0].parameter_numbers()
default_mLen = _ffdh_groups['modp2048'][1]
- if self.dh_p is "":
- self.dh_p = pkcs_i2osp(default_params.p, default_mLen/8)
+ if not self.dh_p:
+ self.dh_p = pkcs_i2osp(default_params.p, default_mLen//8)
if self.dh_plen is None:
self.dh_plen = len(self.dh_p)
- if self.dh_g is "":
+ if not self.dh_g:
self.dh_g = pkcs_i2osp(default_params.g, 1)
if self.dh_glen is None:
self.dh_glen = 1
@@ -321,11 +321,11 @@
g = pkcs_os2ip(self.dh_g)
real_params = dh.DHParameterNumbers(p, g).parameters(default_backend())
- if self.dh_Ys is "":
+ if not self.dh_Ys:
s.server_kx_privkey = real_params.generate_private_key()
pubkey = s.server_kx_privkey.public_key()
y = pubkey.public_numbers().y
- self.dh_Ys = pkcs_i2osp(y, pubkey.key_size/8)
+ self.dh_Ys = pkcs_i2osp(y, pubkey.key_size//8)
# else, we assume that the user wrote the server_kx_privkey by himself
if self.dh_Yslen is None:
self.dh_Yslen = len(self.dh_Ys)
@@ -642,13 +642,13 @@
self.tls_session.server_tmp_rsa_key = k
pubNum = k.pubkey.public_numbers()
- if self.rsamod is "":
- self.rsamod = pkcs_i2osp(pubNum.n, k.pubkey.key_size/8)
+ if not self.rsamod:
+ self.rsamod = pkcs_i2osp(pubNum.n, k.pubkey.key_size//8)
if self.rsamodlen is None:
self.rsamodlen = len(self.rsamod)
rsaexplen = math.ceil(math.log(pubNum.e)/math.log(2)/8.)
- if self.rsaexp is "":
+ if not self.rsaexp:
self.rsaexp = pkcs_i2osp(pubNum.e, rsaexplen)
if self.rsaexplen is None:
self.rsaexplen = len(self.rsaexp)
@@ -722,7 +722,7 @@
s.client_kx_privkey = params.generate_private_key()
pubkey = s.client_kx_privkey.public_key()
y = pubkey.public_numbers().y
- self.dh_Yc = pkcs_i2osp(y, pubkey.key_size/8)
+ self.dh_Yc = pkcs_i2osp(y, pubkey.key_size//8)
if s.client_kx_privkey and s.server_kx_pubkey:
pms = s.client_kx_privkey.exchange(s.server_kx_pubkey)
@@ -730,7 +730,7 @@
s.compute_ms_and_derive_keys()
def post_build(self, pkt, pay):
- if self.dh_Yc == "":
+ if not self.dh_Yc:
try:
self.fill_missing()
except ImportError:
@@ -782,8 +782,8 @@
x = pubkey.public_numbers().x
y = pubkey.public_numbers().y
self.ecdh_Yc = (b"\x04" +
- pkcs_i2osp(x, params.key_size/8) +
- pkcs_i2osp(y, params.key_size/8))
+ pkcs_i2osp(x, params.key_size//8) +
+ pkcs_i2osp(y, params.key_size//8))
if s.client_kx_privkey and s.server_kx_pubkey:
pms = s.client_kx_privkey.exchange(ec.ECDH(), s.server_kx_pubkey)
@@ -791,7 +791,7 @@
s.compute_ms_and_derive_keys()
def post_build(self, pkt, pay):
- if self.ecdh_Yc == "":
+ if not self.ecdh_Yc:
try:
self.fill_missing()
except ImportError:
diff --git a/scapy/layers/tls/keyexchange_tls13.py b/scapy/layers/tls/keyexchange_tls13.py
index 2bbdc51..09af443 100644
--- a/scapy/layers/tls/keyexchange_tls13.py
+++ b/scapy/layers/tls/keyexchange_tls13.py
@@ -84,7 +84,7 @@
if self.group is None:
self.group = 23 # secp256r1
- if self.key_exchange == "":
+ if not self.key_exchange:
try:
self.create_privkey()
except ImportError:
diff --git a/scapy/layers/tls/record.py b/scapy/layers/tls/record.py
index 55a3c08..f2d5024 100644
--- a/scapy/layers/tls/record.py
+++ b/scapy/layers/tls/record.py
@@ -99,7 +99,7 @@
return cls(m, tls_session=pkt.tls_session)
except:
if conf.debug_dissector:
- traceback.print_exc()
+ raise
return Raw(m)
def getfield(self, pkt, s):
@@ -288,6 +288,11 @@
if s.rcs and not isinstance(s.rcs.cipher, Cipher_NULL):
from scapy.layers.tls.record_tls13 import TLS13
return TLS13
+ if _pkt and len(_pkt) < 5:
+ # Layer detected as TLS but too small to be a real packet (len<5).
+ # Those packets appear when sessions are interrupted or to flush buffers.
+ # Scapy should not try to decode them
+ return conf.raw_layer
return TLS
### Parsing methods
@@ -352,7 +357,7 @@
if version > 0x300:
h = alg.digest(read_seq_num + hdr + msg)
elif version == 0x300:
- h = alg.digest_sslv3(read_seq_num + hdr[0] + hdr[3:5] + msg)
+ h = alg.digest_sslv3(read_seq_num + hdr[:1] + hdr[3:5] + msg)
else:
raise Exception("Unrecognized version.")
except HMACError:
diff --git a/scapy/modules/p0f.py b/scapy/modules/p0f.py
index bc312a1..aa1f2e9 100644
--- a/scapy/modules/p0f.py
+++ b/scapy/modules/p0f.py
@@ -22,6 +22,7 @@
from scapy.error import warning, Scapy_Exception, log_runtime
from scapy.volatile import RandInt, RandByte, RandChoice, RandNum, RandShort, RandString
from scapy.sendrecv import sniff
+from scapy.modules import six
from scapy.modules.six.moves import map, range
if conf.route is None:
# unused import, only to initialize conf.route
@@ -359,10 +360,7 @@
if not isinstance(pkt, IP) or not isinstance(pkt.payload, TCP):
raise TypeError("Not a TCP/IP packet")
-
- if uptime is None:
- uptime = random.randint(120,100*60*60*24*365)
-
+
db = p0f_selectdb(pkt.payload.flags)
if osgenre:
pb = db.get_base()
@@ -386,7 +384,15 @@
pers = pb[random.randint(0, len(pb) - 1)]
# options (we start with options because of MSS)
- ## TODO: let the options already set if they are valid
+ # Take the options already set as "hints" to use in the new packet if we
+ # can. MSS, WScale and Timestamp can all be wildcarded in a signature, so
+ # we'll use the already-set values if they're valid integers.
+ orig_opts = dict(pkt.payload.options)
+ int_only = lambda val: val if isinstance(val, six.integer_types) else None
+ mss_hint = int_only(orig_opts.get('MSS'))
+ wscale_hint = int_only(orig_opts.get('WScale'))
+ ts_hint = [int_only(o) for o in orig_opts.get('Timestamp', (None, None))]
+
options = []
if pers[4] != '.':
for opt in pers[4].split(','):
@@ -394,42 +400,73 @@
# MSS might have a maximum size because of window size
# specification
if pers[0][0] == 'S':
- maxmss = (2**16-1) / int(pers[0][1:])
+ maxmss = (2**16-1) // int(pers[0][1:])
else:
maxmss = (2**16-1)
+ # disregard hint if out of range
+ if mss_hint and not 0 <= mss_hint <= maxmss:
+ mss_hint = None
# If we have to randomly pick up a value, we cannot use
# scapy RandXXX() functions, because the value has to be
# set in case we need it for the window size value. That's
# why we use random.randint()
if opt[1:] == '*':
- options.append(('MSS', random.randint(1,maxmss)))
+ if mss_hint is not None:
+ options.append(('MSS', mss_hint))
+ else:
+ options.append(('MSS', random.randint(1, maxmss)))
elif opt[1] == '%':
coef = int(opt[2:])
- options.append(('MSS', coef*random.randint(1,maxmss/coef)))
+ if mss_hint is not None and mss_hint % coef == 0:
+ options.append(('MSS', mss_hint))
+ else:
+ options.append((
+ 'MSS', coef*random.randint(1, maxmss//coef)))
else:
options.append(('MSS', int(opt[1:])))
elif opt[0] == 'W':
+ if wscale_hint and not 0 <= wscale_hint < 2**8:
+ wscale_hint = None
if opt[1:] == '*':
- options.append(('WScale', RandByte()))
+ if wscale_hint is not None:
+ options.append(('WScale', wscale_hint))
+ else:
+ options.append(('WScale', RandByte()))
elif opt[1] == '%':
coef = int(opt[2:])
- options.append(('WScale', coef*RandNum(min=1,
- max=(2**8-1)/coef)))
+ if wscale_hint is not None and wscale_hint % coef == 0:
+ options.append(('WScale', wscale_hint))
+ else:
+ options.append((
+ 'WScale', coef*RandNum(min=1, max=(2**8-1)//coef)))
else:
options.append(('WScale', int(opt[1:])))
elif opt == 'T0':
options.append(('Timestamp', (0, 0)))
elif opt == 'T':
- if 'T' in pers[5]:
+ # Determine first timestamp.
+ if uptime is not None:
+ ts_a = uptime
+ elif ts_hint[0] and 0 < ts_hint[0] < 2**32:
+ # Note: if first ts is 0, p0f registers it as "T0" not "T",
+ # hence we don't want to use the hint if it was 0.
+ ts_a = ts_hint[0]
+ else:
+ ts_a = random.randint(120, 100*60*60*24*365)
+ # Determine second timestamp.
+ if 'T' not in pers[5]:
+ ts_b = 0
+ elif ts_hint[1] and 0 < ts_hint[1] < 2**32:
+ ts_b = ts_hint[1]
+ else:
# FIXME: RandInt() here does not work (bug (?) in
# TCPOptionsField.m2i often raises "OverflowError:
# long int too large to convert to int" in:
# oval = struct.pack(ofmt, *oval)"
# Actually, this is enough to often raise the error:
# struct.pack('I', RandInt())
- options.append(('Timestamp', (uptime, random.randint(1,2**32-1))))
- else:
- options.append(('Timestamp', (uptime, 0)))
+ ts_b = random.randint(1, 2**32-1)
+ options.append(('Timestamp', (ts_a, ts_b)))
elif opt == 'S':
options.append(('SAckOK', ''))
elif opt == 'N':
@@ -457,7 +494,7 @@
pkt.payload.window = int(pers[0])
elif pers[0][0] == '%':
coef = int(pers[0][1:])
- pkt.payload.window = coef * RandNum(min=1,max=(2**16-1)/coef)
+ pkt.payload.window = coef * RandNum(min=1, max=(2**16-1)//coef)
elif pers[0][0] == 'T':
pkt.payload.window = mtu * int(pers[0][1:])
elif pers[0][0] == 'S':
@@ -465,7 +502,7 @@
mss = [x for x in options if x[0] == 'MSS']
if not mss:
raise Scapy_Exception("TCP window value requires MSS, and MSS option not set")
- pkt.payload.window = filter(lambda x: x[0] == 'MSS', options)[0][1] * int(pers[0][1:])
+ pkt.payload.window = mss[0][1] * int(pers[0][1:])
else:
raise Scapy_Exception('Unhandled window size specification')
@@ -487,7 +524,7 @@
if db == p0fo_kdb:
pkt.payload.flags |= 0x20 # U
else:
- pkt.payload.flags |= RandChoice(8, 32, 40) #P / U / PU
+ pkt.payload.flags |= random.choice([8, 32, 40]) # P/U/PU
elif qq == 'D' and db != p0fo_kdb:
pkt /= conf.raw_layer(load=RandString(random.randint(1, 10))) # XXX p0fo.fp
elif qq == 'Q': pkt.payload.seq = pkt.payload.ack
diff --git a/scapy/packet.py b/scapy/packet.py
index 50f0901..9c17050 100644
--- a/scapy/packet.py
+++ b/scapy/packet.py
@@ -497,7 +497,7 @@
if filename is None:
fname = get_temp_file(autoext=".eps")
canvas.writeEPSfile(fname)
- with ContextManagerSubprocess("psdump()"):
+ with ContextManagerSubprocess("psdump()", conf.prog.psreader):
subprocess.Popen([conf.prog.psreader, fname])
else:
canvas.writeEPSfile(filename)
@@ -515,7 +515,7 @@
if filename is None:
fname = get_temp_file(autoext=".pdf")
canvas.writePDFfile(fname)
- with ContextManagerSubprocess("pdfdump()"):
+ with ContextManagerSubprocess("pdfdump()", conf.prog.pdfreader):
subprocess.Popen([conf.prog.pdfreader, fname])
else:
canvas.writePDFfile(filename)
diff --git a/scapy/pton_ntop.py b/scapy/pton_ntop.py
index 0779336..b54a62c 100644
--- a/scapy/pton_ntop.py
+++ b/scapy/pton_ntop.py
@@ -80,10 +80,8 @@
def inet_pton(af, addr):
"""Convert an IP address from text representation into binary form."""
# Will replace Net/Net6 objects
- if not isinstance(addr, str):
- addr = str(addr)
- # Use inet_pton if available
addr = plain_str(addr)
+ # Use inet_pton if available
try:
return socket.inet_pton(af, addr)
except AttributeError:
diff --git a/scapy/sendrecv.py b/scapy/sendrecv.py
index b5c1380..d67e010 100644
--- a/scapy/sendrecv.py
+++ b/scapy/sendrecv.py
@@ -853,7 +853,11 @@
@conf.commands.register
def tshark(*args,**kargs):
- """Sniff packets and print them calling pkt.show(), a bit like text wireshark"""
- sniff(prn=lambda x: x.display(),*args,**kargs)
-
-
+ """Sniff packets and print them calling pkt.summary(), a bit like text wireshark"""
+ print("Capturing on '" + str(kargs.get('iface') if 'iface' in kargs else conf.iface) + "'")
+ i = [0] # This should be a nonlocal variable, using a mutable object for Python 2 compatibility
+ def _cb(pkt):
+ print("%5d\t%s" % (i[0], pkt.summary()))
+ i[0] += 1
+ sniff(prn=_cb, store=False, *args, **kargs)
+ print("\n%d packet%s captured" % (i[0], 's' if i[0] > 1 else ''))
diff --git a/scapy/utils.py b/scapy/utils.py
index b6d481b..8822e01 100644
--- a/scapy/utils.py
+++ b/scapy/utils.py
@@ -429,17 +429,21 @@
>>> subprocess.Popen(["unknown_command"])
"""
- def __init__(self, name):
+ def __init__(self, name, prog):
self.name = name
+ self.prog = prog
def __enter__(self):
pass
def __exit__(self, exc_type, exc_value, traceback):
- if exc_type == OSError:
- msg = "%s: executing %r failed"
- log_runtime.error(msg, self.name, conf.prog.wireshark, exc_info=1)
- return True # Suppress the exception
+ if isinstance(exc_value, (OSError, TypeError)):
+ msg = "%s: executing %r failed" % (self.name, self.prog) if self.prog else "Could not execute %s, is it installed ?" % self.name
+ if not conf.interactive:
+ raise OSError(msg)
+ else:
+ log_runtime.error(msg, exc_info=True)
+ return True # Suppress the exception
class ContextManagerCaptureOutput(object):
"""
@@ -500,7 +504,7 @@
target = get_temp_file(autoext="."+format)
start_viewer = True
else:
- with ContextManagerSubprocess("do_graph()"):
+ with ContextManagerSubprocess("do_graph()", conf.prog.display):
target = subprocess.Popen([conf.prog.display],
stdin=subprocess.PIPE).stdin
if format is not None:
@@ -532,7 +536,7 @@
if conf.prog.display == conf.prog._default:
os.startfile(target.name)
else:
- with ContextManagerSubprocess("do_graph()"):
+ with ContextManagerSubprocess("do_graph()", conf.prog.display):
subprocess.Popen([conf.prog.display, target.name])
_TEX_TR = {
@@ -1214,7 +1218,7 @@
"""Run wireshark on a list of packets"""
f = get_temp_file()
wrpcap(f, pktlist)
- with ContextManagerSubprocess("wireshark()"):
+ with ContextManagerSubprocess("wireshark()", conf.prog.wireshark):
subprocess.Popen([conf.prog.wireshark, "-r", f])
@conf.commands.register
@@ -1275,15 +1279,16 @@
prog = [conf.prog.tcpdump]
elif isinstance(prog, six.string_types):
prog = [prog]
+ _prog_name = "windump()" if WINDOWS else "tcpdump()"
if pktlist is None:
- with ContextManagerSubprocess("tcpdump()"):
+ with ContextManagerSubprocess(_prog_name, prog[0]):
proc = subprocess.Popen(
prog + (args if args is not None else []),
stdout=subprocess.PIPE if dump or getfd else None,
stderr=open(os.devnull) if quiet else None,
)
elif isinstance(pktlist, six.string_types):
- with ContextManagerSubprocess("tcpdump()"):
+ with ContextManagerSubprocess(_prog_name, prog[0]):
proc = subprocess.Popen(
prog + ["-r", pktlist] + (args if args is not None else []),
stdout=subprocess.PIPE if dump or getfd else None,
@@ -1299,7 +1304,7 @@
wrpcap(tmpfile, pktlist)
else:
tmpfile.close()
- with ContextManagerSubprocess("tcpdump()"):
+ with ContextManagerSubprocess(_prog_name, prog[0]):
proc = subprocess.Popen(
prog + ["-r", tmpfile.name] + (args if args is not None else []),
stdout=subprocess.PIPE if dump or getfd else None,
@@ -1307,7 +1312,7 @@
)
conf.temp_files.append(tmpfile.name)
else:
- with ContextManagerSubprocess("tcpdump()"):
+ with ContextManagerSubprocess(_prog_name, prog[0]):
proc = subprocess.Popen(
prog + ["-r", "-"] + (args if args is not None else []),
stdin=subprocess.PIPE,
@@ -1333,7 +1338,7 @@
x = str(x)
f = get_temp_file()
open(f,"wb").write(x)
- with ContextManagerSubprocess("hexedit()"):
+ with ContextManagerSubprocess("hexedit()", conf.prog.hexedit):
subprocess.call([conf.prog.hexedit, f])
x = open(f).read()
os.unlink(f)
diff --git a/scapy/volatile.py b/scapy/volatile.py
index 8b86213..0e963db 100644
--- a/scapy/volatile.py
+++ b/scapy/volatile.py
@@ -121,6 +121,8 @@
return other - self._fix()
def __mul__(self, other):
return self._fix() * other
+ def __rmul__(self, other):
+ return other * self._fix()
def __floordiv__(self, other):
return self._fix() / other
__div__ = __floordiv__
diff --git a/test/can.uts b/test/can.uts
new file mode 100644
index 0000000..ed55dd9
--- /dev/null
+++ b/test/can.uts
@@ -0,0 +1,55 @@
+% Regression tests for the CAN layer
+
+# More informations at http://www.secdev.org/projects/UTscapy/
+
+
+############
+############
+
++ Basic operations
+
+= Load module
+
+load_layer("can")
+
+= Build a packet
+
+pkt = CAN(flags="error", identifier=1234, data="test")
+
+= Dissect & parse
+
+pkt = CAN(raw(pkt))
+pkt.flags == "error" and pkt.identifier == 1234 and pkt.length == 4 and pkt.data == b"test"
+
+
+############
+############
+
++ Example PCAP file
+
+= Read PCAP file
+* From https://wiki.wireshark.org/SampleCaptures?action=AttachFile&do=get&target=CANopen.pca
+
+from io import BytesIO
+pcap_fd = BytesIO(b'\xd4\xc3\xb2\xa1\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\xe3\x00\x00\x00\xe2\xf3mT\x93\x8c\x03\x00\t\x00\x00\x00\t\x00\x00\x00\x00\x00\x073\x01\x00\x00\x00\x00\xe2\xf3mT\xae\x8c\x03\x00\n\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00\x02\x7f\x00\x00\x81\x00\xe2\xf3mTI\x8f\x03\x00\t\x00\x00\x00\t\x00\x00\x00\x00\x00\x07B\x01\x00\x00\x00\x00\xe2\xf3mTM\x8f\x03\x00\t\x00\x00\x00\t\x00\x00\x00\x00\x00\x07c\x01\x00\x00\x00\x00\xe2\xf3mTN\x8f\x03\x00\t\x00\x00\x00\t\x00\x00\x00\x00\x00\x07!\x01\x00\x00\x00\x00\xf8\xf3mTv\x98\x04\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x06B\x08\x7f\x00\x00@\x08\x10\x00\x00\x00\x00\x00\xf8\xf3mT\x96\x98\x04\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x05\xc2\x08\x7f\x00\x00A\x08\x10\x00\x15\x00\x00\x00\xf8\xf3mT\xd4\x98\x04\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x06B\x08\x00\x00\x00`\x00\x00\x00\x00\x00\x00\x00\xf8\xf3mT\x12\x99\x04\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x06B\x08\x00\x00\x00\x80\x00\x00\x00!\x00\x00\x08\xf8\xf3mTC\x99\x04\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x05\xc2\x08\x7f\x00\x00\x00UltraHi\xf8\xf3mTx\x99\x04\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x06B\x08\x00\x00\x00\x80\x00\x00\x00!\x00\x00\x08\xf8\xf3mT\xce\x99\x04\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x06B\x08\x00\x00\x00p\x00\x00\x00\x00\x00\x00\x00\xf8\xf3mT\xe0\x99\x04\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x06B\x08\x00\x00\x00\x80\x00\x00\x00!\x00\x00\x08\xf8\xf3mT \x9a\x04\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x06B\x08\x00\x00\x00\x80\x00\x00\x00!\x00\x00\x08\xf8\xf3mTo\x9a\x04\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x05\xc2\x08\x00\x00\x00\x80\x00\x00\x00!\x00\x00\x083\xf4mTw\xbe\t\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x06B\x08\x7f\x00\x00@\x08\x10*\x00\x00\x00\x003\xf4mT4\xc0\t\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x05\xc2\x08\x00\x00\x00\x80\x08\x10*\x11\x00\t\x06i\xf4mT\xb0\x88\x0c\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x07\xe5\x08\x7f\x00\x00L\x00\x00\x00\x00\x00\x00\x00i\xf4mT+\x89\x0c\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x07\xe4\x08\x7f\x00\x00P\x00\x00\x00\x00\x00\x00\x00i\xf4mT-\x89\x0c\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x07\xe4\x08\x7f\x00\x00P\x00\x00\x00\x00\x00\x00\x00i\xf4mTS\x89\x0c\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x07\xe4\x08\x7f\x00\x00P\x00\x00\x00\x00\x00\x00\x00i\xf4mT\x99\x89\x0c\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x07\xe4\x08\x00\x00\x00P\x00\x00\x00\x00\x00\x00\x00\x8e\xf4mT\x86\xc4\x04\x00\n\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01B\x92\xf4mT\xae\xf0\x07\x00\n\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\xba\xf4mT%\xaa\x0b\x00\n\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02c\xe8\xf4mT\xbc\x0f\x06\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x06B\x08\x7f\x00\x00#\x00b\x01asdf\xe8\xf4mT\x07\x10\x06\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x05\xc2\x08\x00\x00\x00\x80\x00b\x01\x00\x00\x02\x06\x0f\xf5mT\x1c\x81\x00\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x06B\x08\x7f\x00\x00@\x00b\x01\x00\x00\x00\x00\x0f\xf5mT\xfe\x81\x00\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x05\xc2\x08\x00\x00\x00\x80\x00b\x01\x00\x00\x02\x068\xf5mT\x19\xc3\x00\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x06B\x08\x7f\x00\x00\xa0\x08\x10\x00\x10\x00\x00\x008\xf5mTg\xc3\x00\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x05\xc2\x08\x7f\x00\x00\xc2\x08\x10\x00\x15\x00\x00\x008\xf5mT\xd8\xc3\x00\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x06B\x08\x00\x00\x00\x80\x00\x00\x00!\x00\x00\x088\xf5mT\x17\xc4\x00\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x06B\x08\x7f\x00\x00\xa3\x00\x00\x00\x00\x00\x00\x008\xf5mT\xca\xc4\x00\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00\x05\xc2\x08\x00\x00\x00\x80\x00\x00\x00!\x00\x00\x08')
+packets = rdpcap(pcap_fd)
+
+= Check if parsing worked: each packet has a CAN layer
+
+all(CAN in pkt for pkt in packets)
+
+= Check if parsing worked: no packet has a Raw or Padding layer
+
+not any(Raw in pkt or Padding in pkt for pkt in packets)
+
+= Identifiers
+
+set(pkt.identifier for pkt in packets) == {0, 1474, 1602, 1825, 1843, 1858, 1891, 2020, 2021}
+
+= Flags
+
+set(pkt.flags for pkt in packets) == {0}
+
+= Data length
+
+set(pkt.length for pkt in packets) == {1, 2, 8}
diff --git a/test/dnssecRR.uts b/test/dnssecRR.uts
index ab165bd..63599ad 100644
--- a/test/dnssecRR.uts
+++ b/test/dnssecRR.uts
@@ -117,6 +117,11 @@
= DNSRR(type="TXT") instanciation
t = DNSRR(type="TXT", rdata="test")
+= Build DNSRR
+an = DNSRR(type='AAAA', rdata='2001::1')
+an = DNSRR(raw(an))
+assert an.rdata == '2001::1'
+
= DNSRRR(), check parameters
t = DNSRR(b'\x04test\x00\x00\x10\x00\x01\x00\x00\x00\x00\x018\xffScapy is an interactive packet manipulation program that enables you to sniff, mangle, send network packets ; test equipments ; probe and discover networks ; quickly develop new protocols. It can easily handle most classical tasks like scanning, tracerout7ing, probing, unit tests, attacks or network discovery.')
t.type == 16 and t.rdlen == 312 and t.rdata[:5] == b"Scapy" and t.rdata[-10:] == b"discovery."
diff --git a/test/mock_windows.uts b/test/mock_windows.uts
index b016294..1cb1b56 100644
--- a/test/mock_windows.uts
+++ b/test/mock_windows.uts
@@ -193,6 +193,81 @@
test_missing_ifacemetric()
+= Test _get_metrics with weird netsh length
+
+from scapy.arch.windows import _get_metrics
+
+@mock.patch("scapy.arch.windows.POWERSHELL_PROCESS.query")
+def test_get_metrics(mock_exec_query):
+ exc_query_output = """Interface Loopback Pseudo-Interface 1 Parameters
+-------------------------------
+IfLuid : loopback_0
+IfIndex : 1
+State : connected
+Metric : 75
+Link MTU : 4294967295 byt
+Reachable Time : 40500 ms
+Base Reachable Time : 30000 ms
+Retransmission Interval : 1000 ms
+DAD Transmits : 0
+Site Prefix Length : 64
+Site Id : 1
+Forwarding : disabled
+Advertising : disabled
+Neighbor Discovery : disabled
+Neighbor Unreachability Detection : disabled
+Router Discovery : dhcp
+Managed Address Configuration : enabled
+Other Stateful Configuration : enabled
+Weak Host Sends : disabled
+Weak Host Receives : disabled
+Use Automatic Metric : enabled
+Ignore Default Routes : disabled
+Advertised Router Lifetime : 1800 seconds
+Advertise Default Route : disabled
+Current Hop Limit : 0
+Force ARPND Wake up patterns : disabled
+Directed MAC Wake up patterns : disabled
+ECN capability : application
+
+Interface Wi-Fi Parameters
+-------------------------------
+IfLuid : wireless_32768
+IfIndex : 7
+State : connected
+Metric : 55
+Link MTU : 1500 bytes
+Reachable Time : 43500 ms
+Base Reachable Time : 30000 ms
+Retransmission Interval : 1000 ms
+DAD Transmits : 3
+Site Prefix Length : 64
+Site Id : 1
+Forwarding : disabled
+Advertising : disabled
+Neighbor Discovery : enabled
+Neighbor Unreachability Detection : enabled
+Router Discovery : dhcp
+Managed Address Configuration : enabled
+Other Stateful Configuration : enabled
+Weak Host Sends : disabled
+Weak Host Receives : disabled
+Use Automatic Metric : enabled
+Ignore Default Routes : disabled
+Advertised Router Lifetime : 1800 seconds
+Advertise Default Route : disabled
+Current Hop Limit : 0
+Force ARPND Wake up patterns : disabled
+Directed MAC Wake up patterns : disabled
+ECN capability : application
+"""
+ mock_exec_query.side_effect = lambda *args, **kargs: exc_query_output.split("\n")
+ metrics = _get_metrics()
+ print(metrics)
+ assert metrics == {'1': 75, '7': 55}
+
+test_get_metrics()
+
############
############
+ Windows arch unit tests
@@ -206,21 +281,23 @@
from scapy.config import conf
ps_ip = get_ip_from_name(conf.iface.name)
-ps_ip
ps_if_list = get_windows_if_list()
-ps_if_list
ps_read_routes = read_routes()
-ps_read_routes
# Turn on VBS mode
conf.prog.powershell = None
= Test get_ip_from_name with VBS
+ps_ip
+
assert get_ip_from_name(conf.iface.name) == ps_ip
= Test get_windows_if_list with VBS
+ps_if_list
def is_in_if_list(i, list):
+ if not i["mac"]:
+ return True
for j in list:
if j["guid"] == i["guid"] and j["name"] == i["name"]:
return True
@@ -229,20 +306,23 @@
vbs_if_list = get_windows_if_list()
vbs_if_list
_correct = True
-for i in ps_if_list:
- if not is_in_if_list(i, vbs_if_list):
+for i in vbs_if_list:
+ if not is_in_if_list(i, ps_if_list):
_correct = False
break
assert _correct
= Test read_routes with VBS
+ps_read_routes
def is_in_route_list(i, list):
+ # Ignore all empty IP or macs
+ if i[4] == '':
+ return True
+ if i[3].mac == '' or i[3].guid == '' or i[3].ip == '':
+ return True
for j in list:
- #Ignore all empty IP
- if j[4] == '' or i[4] == '':
- return True
if j[2] == i[2] and j[4] == i[4] and j[3].guid == i[3].guid:
return True
return False
@@ -250,8 +330,8 @@
vbs_read_routes = read_routes()
vbs_if_list
_correct = True
-for i in ps_read_routes:
- if not is_in_route_list(i, vbs_read_routes):
+for i in vbs_read_routes:
+ if not is_in_route_list(i, ps_read_routes):
_correct = False
break
diff --git a/test/nmap.uts b/test/nmap.uts
index 3c64e74..2c3d508 100644
--- a/test/nmap.uts
+++ b/test/nmap.uts
@@ -9,6 +9,14 @@
= Module loading
load_module('nmap')
+= Test functions
+
+d = nmap_udppacket_sig(IP()/UDP(), IP(raw(IP()/ICMP(type=3, code=2)/IPerror()/UDPerror())))
+assert len(d) == 9
+
+d = nmap_tcppacket_sig(IP()/TCP())
+assert len(d) == 5
+
= Fetch database
from __future__ import print_function
try:
diff --git a/test/p0f.uts b/test/p0f.uts
new file mode 100644
index 0000000..04f415b
--- /dev/null
+++ b/test/p0f.uts
@@ -0,0 +1,62 @@
+% Tests for Scapy's p0f module.
+
+~ p0f
+
+
+############
+############
++ Basic p0f module tests
+
+= Module loading
+load_module('p0f')
+
+
+############
+############
++ Tests for p0f_impersonate
+
+# XXX: a lot of pieces of p0f_impersonate don't have tests yet.
+
+= Impersonate when window size must be multiple of some integer
+sig = ('%467', 64, 1, 60, 'M*,W*', '.', 'Phony Sys', '1.0')
+pkt = p0f_impersonate(IP()/TCP(), signature=sig)
+assert pkt.payload.window % 467 == 0
+
+= Handle unusual flags ("F") quirk
+sig = ('1024', 64, 0, 60, 'W*', 'F', 'Phony Sys', '1.0')
+pkt = p0f_impersonate(IP()/TCP(), signature=sig)
+assert (pkt.payload.flags & 40) in (8, 32, 40)
+
+= Use valid option values from original packet
+sig = ('S4', 64, 1, 60, 'M*,W*,T', '.', 'Phony Sys', '1.0')
+opts = [('MSS', 1400), ('WScale', 3), ('Timestamp', (97256, 0))]
+pkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)
+assert pkt.payload.options == opts
+
+= Use valid option values when multiples required
+sig = ('S4', 64, 1, 60, 'M%37,W%19', '.', 'Phony Sys', '1.0')
+opts = [('MSS', 37*15), ('WScale', 19*12)]
+pkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)
+assert pkt.payload.options == opts
+
+= Discard non-multiple option values when multiples required
+sig = ('S4', 64, 1, 60, 'M%37,W%19', '.', 'Phony Sys', '1.0')
+opts = [('MSS', 37*15 + 1), ('WScale', 19*12 + 1)]
+pkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)
+assert pkt.payload.options[0][1] % 37 == 0
+assert pkt.payload.options[1][1] % 19 == 0
+
+= Discard bad timestamp values
+sig = ('S4', 64, 1, 60, 'M*,T', '.', 'Phony Sys', '1.0')
+opts = [('Timestamp', (0, 1000))]
+pkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)
+# since option is "T" and not "T0":
+assert pkt.payload.options[1][1][0] > 0
+# since T quirk is not present:
+assert pkt.payload.options[1][1][1] == 0
+
+= Discard 2nd timestamp of 0 if "T" quirk is present
+sig = ('S4', 64, 1, 60, 'M*,T', 'T', 'Phony Sys', '1.0')
+opts = [('Timestamp', (54321, 0))]
+pkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)
+assert pkt.payload.options[1][1][1] > 0
diff --git a/test/regression.uts b/test/regression.uts
index 64f8226..3569724 100644
--- a/test/regression.uts
+++ b/test/regression.uts
@@ -5550,6 +5550,10 @@
values = [tuple(int(val) for val in line[:-1].split(b'\t')) for line in tcpdump(pcapfile, prog=conf.prog.tshark, getfd=True, args=['-T', 'fields', '-e', 'ip.ttl', '-e', 'ip.proto'])]
assert values == [(64, 6), (64, 17), (64, 1)]
+= Run scapy's tshark command
+~ netaccess
+tshark(count=1, timeout=3)
+
= Check Raw IP pcap files
import tempfile
@@ -8134,6 +8138,10 @@
assert(radius_packet.attributes[16].len == 6)
assert(radius_packet.attributes[16].value == 50118)
+= RADIUS - compute_message_authenticator()
+ram = radius_packet[RadiusAttr_Message_Authenticator]
+assert ram.compute_message_authenticator(radius_packet, b"dummy bytes", b"scapy") == b'\x19\xa4\x0e*Y4\xe0l?,\x94\x9f \xb8Jb'
+
= RADIUS - Access-Challenge - Dissection (2)
s = b'\x0b\xae\x00[\xc7\xae\xfc6\xa1=\xb5\x99&^\xdf=\xe9\x00\xa6\xe8\x12\rHello, leapO\x16\x01\x02\x00\x14\x11\x01\x00\x08\xb8\xc4\x1a4\x97x\xd3\x82leapP\x12\xd3\x12\x17\xa6\x0c.\x94\x85\x03]t\xd1\xdb\xd0\x13\x8c\x18\x12iQs\xf7iSb@k\x9d,\xa0\x99\x8ehO'
radius_packet = Radius(s)
@@ -8235,7 +8243,6 @@
assert(radius_packet.attributes[3].value == b'iQs\xf7hRb@k\x9d,\xa0\x99\x8ehO')
= RADIUS - Response Authenticator computation
-~ crypto
s = b'\x01\xae\x01\x17>k\xd4\xc4\x19V\x0b*1\x99\xc8D\xea\xc2\x94Z\x01\x06leap\x06\x06\x00\x00\x00\x02\x1a\x1b\x00\x00\x00\t\x01\x15service-type=Framed\x0c\x06\x00\x00#\xee\x1e\x13AC-7E-8A-4E-E2-92\x1f\x1300-26-73-9E-0F-D3O\x0b\x02\x01\x00\t\x01leapP\x12U\xbc\x12\xcdM\x00\xf8\xdb4\xf1\x18r\xca_\x8c\xf6f\x02\x1a1\x00\x00\x00\t\x01+audit-session-id=0AC8090E0000001A0354CA00\x1a\x14\x00\x00\x00\t\x01\x0emethod=dot1x\x08\x06\xc0\xa8\n\xb9\x04\x06\xc0\xa8\n\x80\x1a\x1d\x00\x00\x00\t\x02\x17GigabitEthernet1/0/18W\x17GigabitEthernet1/0/18=\x06\x00\x00\x00\x0f\x05\x06\x00\x00\xc3\xc6'
access_request = Radius(s)
s = b'\x0b\xae\x00[\xc7\xae\xfc6\xa1=\xb5\x99&^\xdf=\xe9\x00\xa6\xe8\x12\rHello, leapO\x16\x01\x02\x00\x14\x11\x01\x00\x08\xb8\xc4\x1a4\x97x\xd3\x82leapP\x12\xd3\x12\x17\xa6\x0c.\x94\x85\x03]t\xd1\xdb\xd0\x13\x8c\x18\x12iQs\xf7iSb@k\x9d,\xa0\x99\x8ehO'
diff --git a/test/tls.uts b/test/tls.uts
index 84ce41b..ffaf690 100644
--- a/test/tls.uts
+++ b/test/tls.uts
@@ -968,6 +968,9 @@
assert(isinstance(t7.msg[0], _TLSEncryptedContent))
len(t7.msg[0].load) == 478
+= Reading TLS msg dissect - Packet too small
+assert isinstance(TLS(b"\x00"), Raw)
+
= Reading TLS msg dissect - Wrong data
from scapy.layers.tls.record import _TLSMsgListField
assert isinstance(_TLSMsgListField.m2i(_TLSMsgListField("", []), TLS(type=0), '\x00\x03\x03\x00\x03abc'), Raw)
diff --git a/test/tls/tests_tls_netaccess.uts b/test/tls/tests_tls_netaccess.uts
index 63424ca..30ea346 100644
--- a/test/tls/tests_tls_netaccess.uts
+++ b/test/tls/tests_tls_netaccess.uts
@@ -9,7 +9,7 @@
### DISCLAIMER: Those tests are slow ###
= Load server util functions
-~ open_ssl_client
+~ open_ssl_client crypto
from __future__ import print_function
@@ -64,28 +64,29 @@
= Testing TLS server with TLS 1.0 and TLS_RSA_WITH_RC4_128_SHA
-~ open_ssl_client FIXME_py3
+~ open_ssl_client crypto
test_tls_server("RC4-SHA", "-tls1")
= Testing TLS server with TLS 1.1 and TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
-~ open_ssl_client FIXME_py3
+~ open_ssl_client crypto
test_tls_server("EDH-RSA-DES-CBC3-SHA", "-tls1_1")
= Testing TLS server with TLS 1.2 and TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
-~ open_ssl_client FIXME_py3
+~ open_ssl_client crypto
test_tls_server("DHE-RSA-AES128-SHA256", "-tls1_2")
= Testing TLS server with TLS 1.2 and TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
-~ open_ssl_client FIXME_py3
+~ open_ssl_client crypto
test_tls_server("ECDHE-RSA-AES256-GCM-SHA384", "-tls1_2")
+ TLS client automaton tests
= Load client utils functions
+~ crypto
import sys, os, threading
@@ -112,32 +113,32 @@
assert False
= Testing TLS server and client with SSLv2 and SSL_CK_DES_192_EDE3_CBC_WITH_MD5
-~ FIXME_py3
+~ crypto
perform_tls_client_test("0700c0", "0002")
= Testing TLS client with SSLv3 and TLS_RSA_EXPORT_WITH_RC4_40_MD5
-~ FIXME_py3
+~ crypto
perform_tls_client_test("0003", "0300")
= Testing TLS client with TLS 1.0 and TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
-~ FIXME_py3
+~ crypto
perform_tls_client_test("0088", "0301")
= Testing TLS client with TLS 1.1 and TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
-~ FIXME_py3
+~ crypto
perform_tls_client_test("c013", "0302")
= Testing TLS client with TLS 1.2 and TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
-~ FIXME_py3
+~ crypto
perform_tls_client_test("009e", "0303")
= Testing TLS client with TLS 1.2 and TLS_ECDH_anon_WITH_RC4_128_SHA
-~ FIXME_py3
+~ crypto
perform_tls_client_test("c016", "0303")