patch from dwayne c. litzenberger to fix urandom support to work from
within a chroot. i modified it slightly to remove os.urandom calls
completely, since our direct file access is nearly identical to what
python was doing.
This commit is contained in:
Robey Pointer 2008-03-22 14:54:55 -07:00
parent 4f52c13900
commit 613d2a2f24
2 changed files with 91 additions and 44 deletions

View File

@ -65,5 +65,7 @@ test:
# README
# transport.py
#
# TRY on windows vm
# POST gpg sig on website!
# POST md5sum on website!
# RUN setup.py

View File

@ -20,51 +20,43 @@
import sys
# Detect an OS random number source
osrandom_source = None
##
## Find potential random number sources
##
# Try os.urandom
if osrandom_source is None:
try:
from os import urandom
osrandom_source = "os.urandom"
except ImportError:
pass
# Try winrandom
if osrandom_source is None:
try:
from Crypto.Util import winrandom
osrandom_source = "winrandom"
except ImportError:
pass
# Try /dev/urandom
if osrandom_source is None:
# Try to open /dev/urandom now so that paramiko will be able to access
# it even if os.chroot() is invoked later.
try:
_dev_urandom = open("/dev/urandom", "rb", 0)
def urandom(bytes):
return _dev_urandom.read(bytes)
osrandom_source = "/dev/urandom"
except (OSError, IOError):
pass
except EnvironmentError:
_dev_urandom = None
# Try to import the "winrandom" module
try:
from Crypto.Util import winrandom
except ImportError:
winrandom = None
##
## Define RandomPool classes
##
def _workaround_windows_cryptgenrandom_bug(self):
# According to "Cryptanalysis of the Random Number Generator of the
# Windows Operating System", by Leo Dorrendorf and Zvi Gutterman
# and Benny Pinkas <http://eprint.iacr.org/2007/419>,
# CryptGenRandom only updates its internal state using kernel-provided
# random data every 128KiB of output.
self.get_bytes(128*1024) # discard 128 KiB of output
# Give up
if osrandom_source is None:
raise ImportError("Cannot find OS entropy source")
class BaseOSRandomPool(object):
def __init__(self, numbytes=160, cipher=None, hash=None):
pass
def stir(self, s=''):
# According to "Cryptanalysis of the Random Number Generator of the
# Windows Operating System", by Leo Dorrendorf and Zvi Gutterman
# and Benny Pinkas <http://eprint.iacr.org/2007/419>,
# CryptGenRandom only updates its internal state using kernel-provided
# random data every 128KiB of output.
if osrandom_source == 'winrandom' or sys.platform == 'win32':
self.get_bytes(128*1024) # discard 128 KiB of output
pass
def randomize(self, N=0):
self.stir()
@ -72,22 +64,75 @@ class BaseOSRandomPool(object):
def add_event(self, s=None):
pass
class WinrandomOSRandomPool(BaseOSRandomPool):
class WinRandomPool(BaseOSRandomPool):
"""RandomPool that uses the C{winrandom} module for input"""
def __init__(self, numbytes=160, cipher=None, hash=None):
self._wr = winrandom.new()
self.get_bytes = self._wr.get_bytes
self.randomize()
class UrandomOSRandomPool(BaseOSRandomPool):
def stir(self, s=''):
_workaround_windows_cryptgenrandom_bug(self)
class DevUrandomPool(BaseOSRandomPool):
"""RandomPool that uses the C{/dev/urandom} special device node for input"""
def __init__(self, numbytes=160, cipher=None, hash=None):
self.get_bytes = urandom
self.randomize()
if osrandom_source in ("/dev/urandom", "os.urandom"):
OSRandomPool = UrandomOSRandomPool
elif osrandom_source == "winrandom":
OSRandomPool = WinrandomOSRandomPool
else:
raise AssertionError("Unrecognized osrandom_source %r" % (osrandom_source,))
def get_bytes(self, n):
bytes = ""
while len(bytes) < n:
bytes += _dev_urandom.read(n - len(bytes))
return bytes
##
## Detect default random number source
##
osrandom_source = None
# Try /dev/urandom
if osrandom_source is None and _dev_urandom is not None:
osrandom_source = "/dev/urandom"
DefaultRandomPoolClass = DevUrandomPool
# Try winrandom
if osrandom_source is None and winrandom is not None:
osrandom_source = "winrandom"
DefaultRandomPoolClass = WinRandomPool
# Give up
if osrandom_source is None:
raise ImportError("Cannot find OS entropy source")
##
## Define wrapper class
##
class OSRandomPool(object):
"""RandomPool wrapper.
The C{randpool} attribute of this object may be modified by users of this class at runtime.
"""
def __init__(self, instance=None):
if instance is None:
instance = DefaultRandomPoolClass()
self.randpool = instance
def stir(self, s=''):
self.randpool.stir(s)
def randomize(self, N=0):
self.randpool.randomize(N)
def add_event(self, s=None):
self.randpool.add_event(s)
def get_bytes(self, N):
return self.randpool.get_bytes(N)
# vim:set ts=4 sw=4 sts=4 expandtab: