Package paramiko :: Module rng_posix |
[frames] | no frames]

# Source Code for Module paramiko.rng_posix

     1  #!/usr/bin/python
     2  # -*- coding: ascii -*-
     3  # Copyright (C) 2008  Dwayne C. Litzenberger <dlitz@dlitz.net>
     4  # Copyright (C) 2008  Open Systems Canada Limited
     5  #
     6  # This file is part of paramiko.
     7  #
     8  # Paramiko is free software; you can redistribute it and/or modify it under the
     9  # terms of the GNU Lesser General Public License as published by the Free
    10  # Software Foundation; either version 2.1 of the License, or (at your option)
    11  # any later version.
    12  #
    13  # Paramiko is distrubuted in the hope that it will be useful, but WITHOUT ANY
    14  # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
    15  # A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
    16  # details.
    17  #
    18  # You should have received a copy of the GNU Lesser General Public License
    19  # along with Paramiko; if not, write to the Free Software Foundation, Inc.,
    20  # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    21
    22  import os
    23  import stat
    24
    25 -class error(Exception):
    26      pass
    27
    28 -class _RNG(object):
    29 -    def __init__(self, file):
    30          self.file = file
    31
    32 -    def read(self, bytes):
    33          return self.file.read(bytes)
    34
    35 -    def close(self):
    36          return self.file.close()
    37
    38 -    def randomize(self):
    39          return
    40
    41 -def open_rng_device(device_path=None):
    42      """Open /dev/urandom and perform some sanity checks."""
    43
    44      f = None
    45      g = None
    46
    47      if device_path is None:
    48          device_path = "/dev/urandom"
    49
    50      try:
    51          # Try to open /dev/urandom now so that paramiko will be able to access
    52          # it even if os.chroot() is invoked later.
    53          try:
    54              f = open(device_path, "rb", 0)
    55          except EnvironmentError:
    56              raise error("Unable to open /dev/urandom")
    57
    58          # Open a second file descriptor for sanity checking later.
    59          try:
    60              g = open(device_path, "rb", 0)
    61          except EnvironmentError:
    62              raise error("Unable to open /dev/urandom")
    63
    64          # Check that /dev/urandom is a character special device, not a regular file.
    65          st = os.fstat(f.fileno())   # f
    66          if stat.S_ISREG(st.st_mode) or not stat.S_ISCHR(st.st_mode):
    67              raise error("/dev/urandom is not a character special device")
    68
    69          st = os.fstat(g.fileno())   # g
    70          if stat.S_ISREG(st.st_mode) or not stat.S_ISCHR(st.st_mode):
    71              raise error("/dev/urandom is not a character special device")
    72
    73          # Check that /dev/urandom always returns the number of bytes requested
    74          x = f.read(20)
    75          y = g.read(20)
    76          if len(x) != 20 or len(y) != 20:
    77              raise error("Error reading from /dev/urandom: input truncated")
    78
    79          # Check that different reads return different data
    80          if x == y:
    81              raise error("/dev/urandom is broken; returning identical data: %r == %r" % (x, y))
    82
    83          # Close the duplicate file object
    84          g.close()
    85
    86          # Return the first file object
    87          return _RNG(f)
    88
    89      except error:
    90          if f is not None:
    91              f.close()
    92          if g is not None:
    93              g.close()
    94          raise
    95
    96  # vim:set ts=4 sw=4 sts=4 expandtab:
    97