mirror of https://github.com/dirtbags/netarch.git
Major resequencing bugfix + minor fixes
* The resequencer was dropping any data frames after the first FIN/RST. * Make things more Pythony by not changing type checks to try/except * Add an 8-bit-clean caesar implementation to crypto module
This commit is contained in:
parent
237fe5910d
commit
e4c37a3a24
20
__init__.py
20
__init__.py
|
@ -115,16 +115,7 @@ def assert_in(a, *b):
|
|||
|
||||
class BitVector:
|
||||
def __init__(self, i=0, length=None):
|
||||
if type(i) == type(1):
|
||||
self._val = i
|
||||
if length is not None:
|
||||
self._len = length
|
||||
else:
|
||||
self._len = 0
|
||||
while i > 0:
|
||||
i >>= 1
|
||||
self._len += 1
|
||||
else:
|
||||
try:
|
||||
self._val = 0
|
||||
for c in i:
|
||||
self._val <<= 8
|
||||
|
@ -133,6 +124,15 @@ class BitVector:
|
|||
self._len = length
|
||||
else:
|
||||
self._len = len(i) * 8
|
||||
except TypeError:
|
||||
self._val = i
|
||||
if length is not None:
|
||||
self._len = length
|
||||
else:
|
||||
self._len = 0
|
||||
while i > 0:
|
||||
i >>= 1
|
||||
self._len += 1
|
||||
|
||||
def __len__(self):
|
||||
return self._len
|
||||
|
|
|
@ -163,7 +163,7 @@ def neighbors(txt):
|
|||
##
|
||||
|
||||
def rot(n, txt):
|
||||
"""Caesar cipher"""
|
||||
"""Caesar cipher only across letters"""
|
||||
|
||||
out = ""
|
||||
for c in txt:
|
||||
|
@ -178,8 +178,11 @@ def rot(n, txt):
|
|||
return out
|
||||
|
||||
|
||||
def caesar(n, txt):
|
||||
return [chr((ord(c) + n) % 256) for c in txt]
|
||||
|
||||
def caesars(txt):
|
||||
return [rot(i, txt) for i in range(26)]
|
||||
return [caesar(i, txt) for i in range(256)]
|
||||
|
||||
# Tabula recta
|
||||
tabula_recta = caesars('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
|
||||
|
|
45
gapstr.py
45
gapstr.py
|
@ -30,26 +30,29 @@ class GapString:
|
|||
self.length += len(i)
|
||||
self.contents.append(i)
|
||||
except TypeError:
|
||||
self.length += int(i)
|
||||
self.contents.append(int(i))
|
||||
self.length += i
|
||||
self.contents.append(long(i))
|
||||
|
||||
def __str__(self):
|
||||
ret = []
|
||||
for i in self.contents:
|
||||
if isinstance(i, int):
|
||||
try:
|
||||
ret.append(self.drop * i)
|
||||
else:
|
||||
except TypeError:
|
||||
ret.append(i)
|
||||
return ''.join(ret)
|
||||
|
||||
def __iter__(self):
|
||||
for i in self.contents:
|
||||
if isinstance(i, int):
|
||||
for j in range(i):
|
||||
yield self.drop
|
||||
else:
|
||||
try:
|
||||
for c in i:
|
||||
yield c
|
||||
except TypeError:
|
||||
for j in range(i):
|
||||
yield self.drop
|
||||
|
||||
def __nonzero__(self):
|
||||
return self.length > 0
|
||||
|
||||
def hasgaps(self):
|
||||
for i in self.contents:
|
||||
|
@ -62,10 +65,10 @@ class GapString:
|
|||
|
||||
d = __init__.HexDumper(fd)
|
||||
for i in self.contents:
|
||||
if isinstance(i, int):
|
||||
try:
|
||||
for j in range(i):
|
||||
d.dump_drop()
|
||||
else:
|
||||
except TypeError:
|
||||
for c in i:
|
||||
d.dump_chr(c)
|
||||
d.finish()
|
||||
|
@ -90,11 +93,11 @@ class GapString:
|
|||
# Trim off the beginning
|
||||
while start >= 0:
|
||||
i = new.contents.pop(0)
|
||||
if isinstance(i, int):
|
||||
try:
|
||||
start -= i
|
||||
if start < 0:
|
||||
new.contents.insert(0, -start)
|
||||
else:
|
||||
except TypeError:
|
||||
start -= len(i)
|
||||
if start < 0:
|
||||
new.contents.insert(0, i[start:])
|
||||
|
@ -102,11 +105,11 @@ class GapString:
|
|||
# Trim off the end
|
||||
while l >= 0:
|
||||
i = new.contents.pop()
|
||||
if isinstance(i, int):
|
||||
try:
|
||||
l -= i
|
||||
if l < 0:
|
||||
new.contents.append(-l)
|
||||
else:
|
||||
except TypeError:
|
||||
l -= len(i)
|
||||
if l < 0:
|
||||
new.contents.append(i[:-l])
|
||||
|
@ -127,17 +130,15 @@ class GapString:
|
|||
return new
|
||||
|
||||
def __xor__(self, mask):
|
||||
if isinstance(mask, int):
|
||||
mask = [mask]
|
||||
if isinstance(mask, str) or isinstance(mask, GapString):
|
||||
try:
|
||||
mask = [ord(c) for c in mask]
|
||||
except TypeError:
|
||||
mask = [mask]
|
||||
masklen = len(mask)
|
||||
|
||||
new = self.__class__(drop=self.drop)
|
||||
for i in self.contents:
|
||||
if isinstance(i, int):
|
||||
new.append(i)
|
||||
else:
|
||||
try:
|
||||
r = []
|
||||
offset = len(new) % masklen
|
||||
for c in i:
|
||||
|
@ -145,8 +146,12 @@ class GapString:
|
|||
r.append(chr(o ^ mask[offset]))
|
||||
offset = (offset + 1) % masklen
|
||||
new.append(''.join(r))
|
||||
except TypeError:
|
||||
new.append(i)
|
||||
return new
|
||||
|
||||
def startswith(self, what):
|
||||
return (what == str(self[:len(what)]))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
24
ip.py
24
ip.py
|
@ -23,6 +23,7 @@ def unpack_nybbles(byte):
|
|||
|
||||
IP = 0x0800
|
||||
ARP = 0x0806
|
||||
VLAN = 0x8100
|
||||
|
||||
ICMP = 1
|
||||
TCP = 6
|
||||
|
@ -42,6 +43,8 @@ class Frame:
|
|||
self.eth_shost,
|
||||
self.eth_type,
|
||||
p) = unpack('!6s6sH', frame)
|
||||
if self.eth_type == VLAN:
|
||||
_, self.eth_type, p = unpack('!HH', p)
|
||||
if self.eth_type == ARP:
|
||||
# ARP
|
||||
self.name, self.protocol = ('ARP', ARP)
|
||||
|
@ -184,7 +187,7 @@ class TCP_Resequence:
|
|||
self.lastack = [None, None]
|
||||
self.first = None
|
||||
self.pending = [{}, {}]
|
||||
self.closed = 0
|
||||
self.closed = [False, False]
|
||||
self.midstream = False
|
||||
self.hash = 0
|
||||
|
||||
|
@ -198,7 +201,7 @@ class TCP_Resequence:
|
|||
by __init__. The current value of this function is the state.
|
||||
"""
|
||||
|
||||
pass
|
||||
raise NotImplementedError()
|
||||
|
||||
def handle_handshake(self, pkt):
|
||||
if not self.first:
|
||||
|
@ -237,8 +240,12 @@ class TCP_Resequence:
|
|||
# Does this ACK after the last output sequence number?
|
||||
seq = self.lastack[idx]
|
||||
if pkt.ack > seq:
|
||||
if self.closed[idx]:
|
||||
# XXX: If the next thing happens, that means you need to
|
||||
# return a gapstring to deal with dropped frames
|
||||
assert (pkt.ack == seq + 1)
|
||||
return
|
||||
pending = self.pending[xdi]
|
||||
|
||||
# Get a sorted list of sequence numbers
|
||||
keys = pending.keys()
|
||||
keys.sort()
|
||||
|
@ -259,7 +266,11 @@ class TCP_Resequence:
|
|||
# Hopefully just a retransmit...
|
||||
del pending[key]
|
||||
continue
|
||||
elif key == seq:
|
||||
# Default
|
||||
pass
|
||||
elif key > seq:
|
||||
# Dropped frame(s)
|
||||
gs.append(key - seq)
|
||||
seq = key
|
||||
frame = pending[key]
|
||||
|
@ -267,6 +278,7 @@ class TCP_Resequence:
|
|||
seq += len(frame.payload)
|
||||
del pending[key]
|
||||
if seq != pkt.ack:
|
||||
# Drop at the end
|
||||
gs.append(pkt.ack - seq)
|
||||
self.lastack[idx] = pkt.ack
|
||||
|
||||
|
@ -276,14 +288,12 @@ class TCP_Resequence:
|
|||
|
||||
# Is it a FIN or RST?
|
||||
if pkt.flags & (FIN | RST):
|
||||
self.lastack[xdi] = pkt.seq + 1
|
||||
self.closed += 1
|
||||
if self.closed == 2:
|
||||
self.closed[idx] = True
|
||||
if self.closed == 3:
|
||||
# Warn about any unhandled packets
|
||||
if self.pending[0] or self.pending[1]:
|
||||
warnings.warn('Dropping unhandled frames after shutdown' % pkt)
|
||||
self.handle = self.handle_drop
|
||||
ret = None
|
||||
|
||||
return ret
|
||||
|
||||
|
|
Loading…
Reference in New Issue