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