diff options
Diffstat (limited to 'paramiko/rng_posix.py')
-rw-r--r-- | paramiko/rng_posix.py | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/paramiko/rng_posix.py b/paramiko/rng_posix.py new file mode 100644 index 0000000..1e6d72c --- /dev/null +++ b/paramiko/rng_posix.py @@ -0,0 +1,97 @@ +#!/usr/bin/python +# -*- coding: ascii -*- +# Copyright (C) 2008 Dwayne C. Litzenberger <dlitz@dlitz.net> +# Copyright (C) 2008 Open Systems Canada Limited +# +# This file is part of paramiko. +# +# Paramiko is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 2.1 of the License, or (at your option) +# any later version. +# +# Paramiko is distrubuted in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Paramiko; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import os +import stat + +class error(Exception): + pass + +class _RNG(object): + def __init__(self, file): + self.file = file + + def read(self, bytes): + return self.file.read(bytes) + + def close(self): + return self.file.close() + + def randomize(self): + return + +def open_rng_device(device_path=None): + """Open /dev/urandom and perform some sanity checks.""" + + f = None + g = None + + if device_path is None: + device_path = "/dev/urandom" + + try: + # Try to open /dev/urandom now so that paramiko will be able to access + # it even if os.chroot() is invoked later. + try: + f = open(device_path, "rb", 0) + except EnvironmentError: + raise error("Unable to open /dev/urandom") + + # Open a second file descriptor for sanity checking later. + try: + g = open(device_path, "rb", 0) + except EnvironmentError: + raise error("Unable to open /dev/urandom") + + # Check that /dev/urandom is a character special device, not a regular file. + st = os.fstat(f.fileno()) # f + if stat.S_ISREG(st.st_mode) or not stat.S_ISCHR(st.st_mode): + raise error("/dev/urandom is not a character special device") + + st = os.fstat(g.fileno()) # g + if stat.S_ISREG(st.st_mode) or not stat.S_ISCHR(st.st_mode): + raise error("/dev/urandom is not a character special device") + + # Check that /dev/urandom always returns the number of bytes requested + x = f.read(20) + y = g.read(20) + if len(x) != 20 or len(y) != 20: + raise error("Error reading from /dev/urandom: input truncated") + + # Check that different reads return different data + if x == y: + raise error("/dev/urandom is broken; returning identical data: %r == %r" % (x, y)) + + # Close the duplicate file object + g.close() + + # Return the first file object + return _RNG(f) + + except error: + if f is not None: + f.close() + if g is not None: + g.close() + raise + +# vim:set ts=4 sw=4 sts=4 expandtab: + |