[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[minion-cvs] Add basic functionality to ameliorate zlib bombing
Update of /home/minion/cvsroot/src/minion/lib/mixminion
In directory moria.mit.edu:/tmp/cvs-serv3253/lib/mixminion
Modified Files:
Crypto.py BuildMessage.py
Log Message:
Add basic functionality to ameliorate zlib bombing
Index: Crypto.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Crypto.py,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- Crypto.py 16 Dec 2002 02:40:11 -0000 1.28
+++ Crypto.py 20 Dec 2002 23:51:22 -0000 1.29
@@ -18,13 +18,14 @@
from mixminion.Common import MixError, MixFatalError, floorDiv, ceilDiv, LOG
__all__ = [ 'AESCounterPRNG', 'CryptoError', 'Keyset', 'bear_decrypt',
- 'bear_encrypt', 'ctr_crypt', 'init_crypto', 'lioness_decrypt',
- 'lioness_encrypt', 'openssl_seed', 'pk_check_signature',
- 'pk_decode_private_key', 'pk_decrypt', 'pk_encode_private_key',
- 'pk_encrypt', 'pk_from_modulus', 'pk_generate', 'pk_get_modulus',
- 'pk_sign', 'prng', 'sha1', 'strxor', 'trng',
- 'AES_KEY_LEN', 'DIGEST_LEN', 'HEADER_SECRET_MODE', 'PRNG_MODE',
- 'RANDOM_JUNK_MODE', 'HEADER_ENCRYPT_MODE', 'APPLICATION_KEY_MODE',
+ 'bear_encrypt', 'ctr_crypt', 'getCommonPRNG', 'init_crypto',
+ 'lioness_decrypt', 'lioness_encrypt', 'openssl_seed',
+ 'pk_check_signature', 'pk_decode_private_key', 'pk_decrypt',
+ 'pk_encode_private_key', 'pk_encrypt', 'pk_from_modulus',
+ 'pk_generate', 'pk_get_modulus', 'pk_sign', 'prng', 'sha1',
+ 'strxor', 'trng', 'AES_KEY_LEN', 'DIGEST_LEN',
+ 'HEADER_SECRET_MODE', 'PRNG_MODE', 'RANDOM_JUNK_MODE',
+ 'HEADER_ENCRYPT_MODE', 'APPLICATION_KEY_MODE',
'PAYLOAD_ENCRYPT_MODE', 'HIDE_HEADER_MODE' ]
# Expose _minionlib.CryptoError as Crypto.CryptoError
Index: BuildMessage.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/BuildMessage.py,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- BuildMessage.py 16 Dec 2002 02:40:11 -0000 1.23
+++ BuildMessage.py 20 Dec 2002 23:51:22 -0000 1.24
@@ -551,8 +551,18 @@
assert overhead in (0, ENC_FWD_OVERHEAD)
# Compress the data, and figure out how much padding we'll need.
+ origLength = len(payload)
payload = compressData(payload)
length = len(payload)
+
+ # FFFF This is an ugly workaround for too-compressable data, so we don't
+ # FFFF create messages that will necessarily be dropped. We should be
+ # FFFF more sensible on the output side.
+ if length > 1024 and length*20 <= origLength:
+ LOG.warn("Double-compressing message so it won't look like a z-bomb")
+ payload = compressData(payload)
+ length = len(payload)
+
paddingLen = PAYLOAD_LEN - SINGLETON_PAYLOAD_OVERHEAD - overhead - length
# If the compressed payload doesn't fit in 28K, then we need to bail out.
@@ -583,7 +593,13 @@
raise MixError("Message fragments not yet supported")
# Uncompress the body.
- return uncompressData(payload.getContents())
+ contents = payload.getContents()
+ # FFFF - We should make this rule configurable.
+ maxLen = max(20*1024, 20*len(contents))
+ # FFFF - On encountering an overcompressed piece of data, we should
+ # FFFF deliver it, still compressed, with a warning -- not merely
+ # FFFF drop it as a _definite_ bomb.
+ return uncompressData(payload.getContents(), maxLength=maxLen)
def _checkPayload(payload):
'Return true iff the hash on the given payload seems valid'
@@ -620,12 +636,16 @@
assert s[1] == '\xda' # no dict, max compression
return s
-def uncompressData(payload):
- """Uncompress a string 'payload'; raise ParseError if it is not valid
- compressed data."""
- # FFFF We should prevent zlib bombing. Somebody could compress 28MB of
- # FFFF zero bytes down to fit in a single payload and use us to
- # FFFF mailbomb people, hard.
+class CompressedDataTooLong(MixError):
+ """Exception: raised when try to uncompress data that turns out to be
+ longer than we had expected."""
+ pass
+
+def uncompressData(payload, maxLength=None):
+ """Uncompress a string 'payload'; raise ParseError if it is not
+ valid compressed data. If the expanded data is longer than
+ maxLength, we raise 'CompressedDataTooLong'."""
+
if len(payload) < 6 or payload[0:2] != '\x78\xDA':
raise ParseError("Invalid zlib header")
try:
@@ -633,7 +653,13 @@
# want to limit the output size.
zobj = zlib.decompressobj(zlib.MAX_WBITS)
# Decompress the payload.
- d = zobj.decompress(payload)
+ if maxLength is None:
+ d = zobj.decompress(payload)
+ else:
+ d = zobj.decompress(payload, maxLength)
+ if zobj.unconsumed_tail:
+ raise CompressedDataTooLong()
+
# Get any leftovers, which shouldn't exist.
nil = zobj.flush()
if nil != '':