aboutsummaryrefslogtreecommitdiff
path: root/paramiko/rng_posix.py
diff options
context:
space:
mode:
Diffstat (limited to 'paramiko/rng_posix.py')
-rw-r--r--paramiko/rng_posix.py97
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:
+