~ubuntu-branches/ubuntu/saucy/paramiko/saucy

« back to all changes in this revision

Viewing changes to debian/patches/01_no-randompool.patch

  • Committer: Bazaar Package Importer
  • Author(s): Jelmer Vernooij
  • Date: 2011-01-28 12:35:12 UTC
  • Revision ID: james.westby@ubuntu.com-20110128123512-x2v78l6cb00217ur
Tags: 1.7.6-5.1
* Non-maintainer upload.
* Avoid deprecated RandomPool. Patch by Gary van der Merwe. Closes:
  #576697
* Switch to source format 3.0 (quilt).
* Try connecting to each available address family until one succeeds.
  Patch by Andrew Bennetts.  Closes: #602251
* Bump standards version to 3.9.1 (no changes).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
=== modified file 'a/paramiko/__init__.py'
 
2
--- a/paramiko/__init__.py      2010-04-26 00:05:06 +0000
 
3
+++ b/paramiko/__init__.py      2010-08-02 22:13:08 +0000
 
4
@@ -66,7 +66,7 @@
 
5
 __license__ = "GNU Lesser General Public License (LGPL)"
 
6
 
 
7
 
 
8
-from transport import randpool, SecurityOptions, Transport
 
9
+from transport import SecurityOptions, Transport
 
10
 from client import SSHClient, MissingHostKeyPolicy, AutoAddPolicy, RejectPolicy, WarningPolicy
 
11
 from auth_handler import AuthHandler
 
12
 from channel import Channel, ChannelFile
 
13
 
 
14
=== modified file 'a/paramiko/agent.py'
 
15
--- a/paramiko/agent.py 2007-02-13 19:17:06 +0000
 
16
+++ b/paramiko/agent.py 2010-08-02 22:13:08 +0000
 
17
@@ -139,7 +139,7 @@
 
18
     def get_name(self):
 
19
         return self.name
 
20
 
 
21
-    def sign_ssh_data(self, randpool, data):
 
22
+    def sign_ssh_data(self, rng, data):
 
23
         msg = Message()
 
24
         msg.add_byte(chr(SSH2_AGENTC_SIGN_REQUEST))
 
25
         msg.add_string(self.blob)
 
26
 
 
27
=== modified file 'a/paramiko/auth_handler.py'
 
28
--- a/paramiko/auth_handler.py  2009-07-20 02:45:02 +0000
 
29
+++ b/paramiko/auth_handler.py  2010-08-02 22:13:08 +0000
 
30
@@ -206,7 +206,7 @@
 
31
                 m.add_string(self.private_key.get_name())
 
32
                 m.add_string(str(self.private_key))
 
33
                 blob = self._get_session_blob(self.private_key, 'ssh-connection', self.username)
 
34
-                sig = self.private_key.sign_ssh_data(self.transport.randpool, blob)
 
35
+                sig = self.private_key.sign_ssh_data(self.transport.rng, blob)
 
36
                 m.add_string(str(sig))
 
37
             elif self.auth_method == 'keyboard-interactive':
 
38
                 m.add_string('')
 
39
 
 
40
=== modified file 'a/paramiko/channel.py'
 
41
--- a/paramiko/channel.py       2009-11-01 00:55:52 +0000
 
42
+++ b/paramiko/channel.py       2010-08-02 22:13:08 +0000
 
43
@@ -364,7 +364,7 @@
 
44
         if auth_protocol is None:
 
45
             auth_protocol = 'MIT-MAGIC-COOKIE-1'
 
46
         if auth_cookie is None:
 
47
-            auth_cookie = binascii.hexlify(self.transport.randpool.get_bytes(16))
 
48
+            auth_cookie = binascii.hexlify(self.transport.rng.read(16))
 
49
 
 
50
         m = Message()
 
51
         m.add_byte(chr(MSG_CHANNEL_REQUEST))
 
52
 
 
53
=== modified file 'a/paramiko/common.py'
 
54
--- a/paramiko/common.py        2009-07-20 02:45:02 +0000
 
55
+++ b/paramiko/common.py        2010-08-02 22:13:08 +0000
 
56
@@ -95,10 +95,10 @@
 
57
 DISCONNECT_SERVICE_NOT_AVAILABLE, DISCONNECT_AUTH_CANCELLED_BY_USER, \
 
58
     DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE = 7, 13, 14
 
59
 
 
60
-from rng import StrongLockingRandomPool
 
61
+from Crypto import Random
 
62
 
 
63
 # keep a crypto-strong PRNG nearby
 
64
-randpool = StrongLockingRandomPool()
 
65
+rng = Random.new()
 
66
 
 
67
 import sys
 
68
 if sys.version_info < (2, 3):
 
69
 
 
70
=== modified file 'a/paramiko/dsskey.py'
 
71
--- a/paramiko/dsskey.py        2009-07-20 02:45:02 +0000
 
72
+++ b/paramiko/dsskey.py        2010-08-02 22:13:08 +0000
 
73
@@ -91,13 +91,13 @@
 
74
     def can_sign(self):
 
75
         return self.x is not None
 
76
 
 
77
-    def sign_ssh_data(self, rpool, data):
 
78
+    def sign_ssh_data(self, rng, data):
 
79
         digest = SHA.new(data).digest()
 
80
         dss = DSA.construct((long(self.y), long(self.g), long(self.p), long(self.q), long(self.x)))
 
81
         # generate a suitable k
 
82
         qsize = len(util.deflate_long(self.q, 0))
 
83
         while True:
 
84
-            k = util.inflate_long(rpool.get_bytes(qsize), 1)
 
85
+            k = util.inflate_long(rng.read(qsize), 1)
 
86
             if (k > 2) and (k < self.q):
 
87
                 break
 
88
         r, s = dss.sign(util.inflate_long(digest, 1), k)
 
89
@@ -161,8 +161,7 @@
 
90
         @return: new private key
 
91
         @rtype: L{DSSKey}
 
92
         """
 
93
-        randpool.stir()
 
94
-        dsa = DSA.generate(bits, randpool.get_bytes, progress_func)
 
95
+        dsa = DSA.generate(bits, rng.read, progress_func)
 
96
         key = DSSKey(vals=(dsa.p, dsa.q, dsa.g, dsa.y))
 
97
         key.x = dsa.x
 
98
         return key
 
99
 
 
100
=== modified file 'a/paramiko/hostkeys.py'
 
101
--- a/paramiko/hostkeys.py      2009-11-02 05:33:13 +0000
 
102
+++ b/paramiko/hostkeys.py      2010-08-02 22:13:08 +0000
 
103
@@ -303,7 +303,7 @@
 
104
         @rtype: str
 
105
         """
 
106
         if salt is None:
 
107
-            salt = randpool.get_bytes(SHA.digest_size)
 
108
+            salt = rng.read(SHA.digest_size)
 
109
         else:
 
110
             if salt.startswith('|1|'):
 
111
                 salt = salt.split('|')[2]
 
112
 
 
113
=== modified file 'a/paramiko/kex_gex.py'
 
114
--- a/paramiko/kex_gex.py       2009-07-20 02:45:02 +0000
 
115
+++ b/paramiko/kex_gex.py       2010-08-02 22:13:08 +0000
 
116
@@ -101,8 +101,7 @@
 
117
             qhbyte <<= 1
 
118
             qmask >>= 1
 
119
         while True:
 
120
-            self.transport.randpool.stir()
 
121
-            x_bytes = self.transport.randpool.get_bytes(bytes)
 
122
+            x_bytes = self.transport.rng.read(bytes)
 
123
             x_bytes = chr(ord(x_bytes[0]) & qmask) + x_bytes[1:]
 
124
             x = util.inflate_long(x_bytes, 1)
 
125
             if (x > 1) and (x < q):
 
126
@@ -207,7 +206,7 @@
 
127
         H = SHA.new(str(hm)).digest()
 
128
         self.transport._set_K_H(K, H)
 
129
         # sign it
 
130
-        sig = self.transport.get_server_key().sign_ssh_data(self.transport.randpool, H)
 
131
+        sig = self.transport.get_server_key().sign_ssh_data(self.transport.rng, H)
 
132
         # send reply
 
133
         m = Message()
 
134
         m.add_byte(chr(_MSG_KEXDH_GEX_REPLY))
 
135
 
 
136
=== modified file 'a/paramiko/kex_group1.py'
 
137
--- a/paramiko/kex_group1.py    2009-07-20 02:45:02 +0000
 
138
+++ b/paramiko/kex_group1.py    2010-08-02 22:13:08 +0000
 
139
@@ -79,8 +79,7 @@
 
140
         # potential x where the first 63 bits are 1, because some of those will be
 
141
         # larger than q (but this is a tiny tiny subset of potential x).
 
142
         while 1:
 
143
-            self.transport.randpool.stir()
 
144
-            x_bytes = self.transport.randpool.get_bytes(128)
 
145
+            x_bytes = self.transport.rng.read(128)
 
146
             x_bytes = chr(ord(x_bytes[0]) & 0x7f) + x_bytes[1:]
 
147
             if (x_bytes[:8] != '\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF') and \
 
148
                    (x_bytes[:8] != '\x00\x00\x00\x00\x00\x00\x00\x00'):
 
149
@@ -125,7 +124,7 @@
 
150
         H = SHA.new(str(hm)).digest()
 
151
         self.transport._set_K_H(K, H)
 
152
         # sign it
 
153
-        sig = self.transport.get_server_key().sign_ssh_data(self.transport.randpool, H)
 
154
+        sig = self.transport.get_server_key().sign_ssh_data(self.transport.rng, H)
 
155
         # send reply
 
156
         m = Message()
 
157
         m.add_byte(chr(_MSG_KEXDH_REPLY))
 
158
 
 
159
=== modified file 'a/paramiko/packet.py'
 
160
--- a/paramiko/packet.py        2010-04-14 01:51:45 +0000
 
161
+++ b/paramiko/packet.py        2010-08-02 22:13:08 +0000
 
162
@@ -311,9 +311,6 @@
 
163
 
 
164
             self.__sent_bytes += len(out)
 
165
             self.__sent_packets += 1
 
166
-            if (self.__sent_packets % 100) == 0:
 
167
-                # stirring the randpool takes 30ms on my ibook!!
 
168
-                randpool.stir()
 
169
             if ((self.__sent_packets >= self.REKEY_PACKETS) or (self.__sent_bytes >= self.REKEY_BYTES)) \
 
170
                    and not self.__need_rekey:
 
171
                 # only ask once for rekeying
 
172
@@ -359,7 +356,7 @@
 
173
                 raise SSHException('Mismatched MAC')
 
174
         padding = ord(packet[0])
 
175
         payload = packet[1:packet_size - padding]
 
176
-        randpool.add_event()
 
177
+        
 
178
         if self.__dump_packets:
 
179
             self._log(DEBUG, 'Got payload (%d bytes, %d padding)' % (packet_size, padding))
 
180
 
 
181
@@ -476,7 +473,7 @@
 
182
         packet = struct.pack('>IB', len(payload) + padding + 1, padding)
 
183
         packet += payload
 
184
         if self.__block_engine_out is not None:
 
185
-            packet += randpool.get_bytes(padding)
 
186
+            packet += rng.read(padding)
 
187
         else:
 
188
             # cute trick i caught openssh doing: if we're not encrypting,
 
189
             # don't waste random bytes for the padding
 
190
 
 
191
=== modified file 'a/paramiko/pkey.py'
 
192
--- a/paramiko/pkey.py  2009-07-20 02:45:02 +0000
 
193
+++ b/paramiko/pkey.py  2010-08-02 22:13:08 +0000
 
194
@@ -143,13 +143,13 @@
 
195
         """
 
196
         return base64.encodestring(str(self)).replace('\n', '')
 
197
 
 
198
-    def sign_ssh_data(self, randpool, data):
 
199
+    def sign_ssh_data(self, rng, data):
 
200
         """
 
201
         Sign a blob of data with this private key, and return a L{Message}
 
202
         representing an SSH signature message.
 
203
 
 
204
-        @param randpool: a secure random number generator.
 
205
-        @type randpool: L{Crypto.Util.randpool.RandomPool}
 
206
+        @param rng: a secure random number generator.
 
207
+        @type rng: L{Crypto.Util.rng.RandomPool}
 
208
         @param data: the data to sign.
 
209
         @type data: str
 
210
         @return: an SSH signature message.
 
211
@@ -360,11 +360,11 @@
 
212
             keysize = self._CIPHER_TABLE[cipher_name]['keysize']
 
213
             blocksize = self._CIPHER_TABLE[cipher_name]['blocksize']
 
214
             mode = self._CIPHER_TABLE[cipher_name]['mode']
 
215
-            salt = randpool.get_bytes(8)
 
216
+            salt = rng.read(8)
 
217
             key = util.generate_key_bytes(MD5, salt, password, keysize)
 
218
             if len(data) % blocksize != 0:
 
219
                 n = blocksize - len(data) % blocksize
 
220
-                #data += randpool.get_bytes(n)
 
221
+                #data += rng.read(n)
 
222
                 # that would make more sense ^, but it confuses openssh.
 
223
                 data += '\0' * n
 
224
             data = cipher.new(key, mode, salt).encrypt(data)
 
225
 
 
226
=== modified file 'a/paramiko/primes.py'
 
227
--- a/paramiko/primes.py        2009-07-20 02:45:02 +0000
 
228
+++ b/paramiko/primes.py        2010-08-02 22:13:08 +0000
 
229
@@ -26,12 +26,12 @@
 
230
 from paramiko.ssh_exception import SSHException
 
231
 
 
232
 
 
233
-def _generate_prime(bits, randpool):
 
234
+def _generate_prime(bits, rng):
 
235
     "primtive attempt at prime generation"
 
236
     hbyte_mask = pow(2, bits % 8) - 1
 
237
     while True:
 
238
         # loop catches the case where we increment n into a higher bit-range
 
239
-        x = randpool.get_bytes((bits+7) // 8)
 
240
+        x = rng.read((bits+7) // 8)
 
241
         if hbyte_mask > 0:
 
242
             x = chr(ord(x[0]) & hbyte_mask) + x[1:]
 
243
         n = util.inflate_long(x, 1)
 
244
@@ -43,7 +43,7 @@
 
245
             break
 
246
     return n
 
247
 
 
248
-def _roll_random(rpool, n):
 
249
+def _roll_random(rng, n):
 
250
     "returns a random # from 0 to N-1"
 
251
     bits = util.bit_length(n-1)
 
252
     bytes = (bits + 7) // 8
 
253
@@ -56,7 +56,7 @@
 
254
     # fits, so i can't guarantee that this loop will ever finish, but the odds
 
255
     # of it looping forever should be infinitesimal.
 
256
     while True:
 
257
-        x = rpool.get_bytes(bytes)
 
258
+        x = rng.read(bytes)
 
259
         if hbyte_mask > 0:
 
260
             x = chr(ord(x[0]) & hbyte_mask) + x[1:]
 
261
         num = util.inflate_long(x, 1)
 
262
@@ -75,7 +75,7 @@
 
263
         # pack is a hash of: bits -> [ (generator, modulus) ... ]
 
264
         self.pack = {}
 
265
         self.discarded = []
 
266
-        self.randpool = rpool
 
267
+        self.rng = rpool
 
268
 
 
269
     def _parse_modulus(self, line):
 
270
         timestamp, mod_type, tests, tries, size, generator, modulus = line.split()
 
271
@@ -147,5 +147,5 @@
 
272
             if min > good:
 
273
                 good = bitsizes[-1]
 
274
         # now pick a random modulus of this bitsize
 
275
-        n = _roll_random(self.randpool, len(self.pack[good]))
 
276
+        n = _roll_random(self.rng, len(self.pack[good]))
 
277
         return self.pack[good][n]
 
278
 
 
279
=== removed file 'a/paramiko/rng.py'
 
280
--- a/paramiko/rng.py   2008-05-18 22:45:25 +0000
 
281
+++ b/paramiko/rng.py   1970-01-01 00:00:00 +0000
 
282
@@ -1,112 +0,0 @@
 
283
-#!/usr/bin/python
 
284
-# -*- coding: ascii -*-
 
285
-# Copyright (C) 2008  Dwayne C. Litzenberger <dlitz@dlitz.net>
 
286
-#
 
287
-# This file is part of paramiko.
 
288
-#
 
289
-# Paramiko is free software; you can redistribute it and/or modify it under the
 
290
-# terms of the GNU Lesser General Public License as published by the Free
 
291
-# Software Foundation; either version 2.1 of the License, or (at your option)
 
292
-# any later version.
 
293
-#
 
294
-# Paramiko is distrubuted in the hope that it will be useful, but WITHOUT ANY
 
295
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 
296
-# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
 
297
-# details.
 
298
-#
 
299
-# You should have received a copy of the GNU Lesser General Public License
 
300
-# along with Paramiko; if not, write to the Free Software Foundation, Inc.,
 
301
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
302
-
 
303
-import sys
 
304
-import threading
 
305
-from Crypto.Util.randpool import RandomPool as _RandomPool
 
306
-
 
307
-try:
 
308
-    import platform
 
309
-except ImportError:
 
310
-    platform = None     # Not available using Python 2.2
 
311
-
 
312
-def _strxor(a, b):
 
313
-    assert len(a) == len(b)
 
314
-    return "".join(map(lambda x, y: chr(ord(x) ^ ord(y)), a, b))
 
315
-
 
316
-##
 
317
-## Find a strong random entropy source, depending on the detected platform.
 
318
-## WARNING TO DEVELOPERS: This will fail on some systems, but do NOT use
 
319
-## Crypto.Util.randpool.RandomPool as a fall-back.  RandomPool will happily run
 
320
-## with very little entropy, thus _silently_ defeating any security that
 
321
-## Paramiko attempts to provide.  (This is current as of PyCrypto 2.0.1).
 
322
-## See http://www.lag.net/pipermail/paramiko/2008-January/000599.html
 
323
-## and http://www.lag.net/pipermail/paramiko/2008-April/000678.html
 
324
-##
 
325
-
 
326
-if ((platform is not None and platform.system().lower() == 'windows') or
 
327
-        sys.platform == 'win32'):
 
328
-    # MS Windows
 
329
-    from paramiko import rng_win32
 
330
-    rng_device = rng_win32.open_rng_device()
 
331
-else:
 
332
-    # Assume POSIX (any system where /dev/urandom exists)
 
333
-    from paramiko import rng_posix
 
334
-    rng_device = rng_posix.open_rng_device()
 
335
-
 
336
-
 
337
-class StrongLockingRandomPool(object):
 
338
-    """Wrapper around RandomPool guaranteeing strong random numbers.
 
339
-    
 
340
-    Crypto.Util.randpool.RandomPool will silently operate even if it is seeded
 
341
-    with little or no entropy, and it provides no prediction resistance if its
 
342
-    state is ever compromised throughout its runtime.  It is also not thread-safe.
 
343
-
 
344
-    This wrapper augments RandomPool by XORing its output with random bits from
 
345
-    the operating system, and by controlling access to the underlying
 
346
-    RandomPool using an exclusive lock.
 
347
-    """
 
348
-
 
349
-    def __init__(self, instance=None):
 
350
-        if instance is None:
 
351
-            instance = _RandomPool()
 
352
-        self.randpool = instance
 
353
-        self.randpool_lock = threading.Lock()
 
354
-        self.entropy = rng_device
 
355
-
 
356
-        # Stir 256 bits of entropy from the RNG device into the RandomPool.
 
357
-        self.randpool.stir(self.entropy.read(32))
 
358
-        self.entropy.randomize()
 
359
-
 
360
-    def stir(self, s=''):
 
361
-        self.randpool_lock.acquire()
 
362
-        try:
 
363
-            self.randpool.stir(s)
 
364
-        finally:
 
365
-            self.randpool_lock.release()
 
366
-        self.entropy.randomize()
 
367
-
 
368
-    def randomize(self, N=0):
 
369
-        self.randpool_lock.acquire()
 
370
-        try:
 
371
-            self.randpool.randomize(N)
 
372
-        finally:
 
373
-            self.randpool_lock.release()
 
374
-        self.entropy.randomize()
 
375
-
 
376
-    def add_event(self, s=''):
 
377
-        self.randpool_lock.acquire()
 
378
-        try:
 
379
-            self.randpool.add_event(s)
 
380
-        finally:
 
381
-            self.randpool_lock.release()
 
382
-
 
383
-    def get_bytes(self, N):
 
384
-        self.randpool_lock.acquire()
 
385
-        try:
 
386
-            randpool_data = self.randpool.get_bytes(N)
 
387
-        finally:
 
388
-            self.randpool_lock.release()
 
389
-        entropy_data = self.entropy.read(N)
 
390
-        result = _strxor(randpool_data, entropy_data)
 
391
-        assert len(randpool_data) == N and len(entropy_data) == N and len(result) == N
 
392
-        return result
 
393
-
 
394
-# vim:set ts=4 sw=4 sts=4 expandtab:
 
395
 
 
396
=== removed file 'a/paramiko/rng_posix.py'
 
397
--- a/paramiko/rng_posix.py     2009-11-02 05:33:13 +0000
 
398
+++ b/paramiko/rng_posix.py     1970-01-01 00:00:00 +0000
 
399
@@ -1,97 +0,0 @@
 
400
-#!/usr/bin/python
 
401
-# -*- coding: ascii -*-
 
402
-# Copyright (C) 2008  Dwayne C. Litzenberger <dlitz@dlitz.net>
 
403
-# Copyright (C) 2008  Open Systems Canada Limited
 
404
-#
 
405
-# This file is part of paramiko.
 
406
-#
 
407
-# Paramiko is free software; you can redistribute it and/or modify it under the
 
408
-# terms of the GNU Lesser General Public License as published by the Free
 
409
-# Software Foundation; either version 2.1 of the License, or (at your option)
 
410
-# any later version.
 
411
-#
 
412
-# Paramiko is distrubuted in the hope that it will be useful, but WITHOUT ANY
 
413
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 
414
-# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
 
415
-# details.
 
416
-#
 
417
-# You should have received a copy of the GNU Lesser General Public License
 
418
-# along with Paramiko; if not, write to the Free Software Foundation, Inc.,
 
419
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
420
-
 
421
-import os
 
422
-import stat
 
423
-
 
424
-class error(Exception):
 
425
-    pass
 
426
-
 
427
-class _RNG(object):
 
428
-    def __init__(self, file):
 
429
-        self.file = file
 
430
-
 
431
-    def read(self, bytes):
 
432
-        return self.file.read(bytes)
 
433
-
 
434
-    def close(self):
 
435
-        return self.file.close()
 
436
-
 
437
-    def randomize(self):
 
438
-        return
 
439
-
 
440
-def open_rng_device(device_path=None):
 
441
-    """Open /dev/urandom and perform some sanity checks."""
 
442
-
 
443
-    f = None
 
444
-    g = None
 
445
-
 
446
-    if device_path is None:
 
447
-        device_path = "/dev/urandom"
 
448
-
 
449
-    try:
 
450
-        # Try to open /dev/urandom now so that paramiko will be able to access
 
451
-        # it even if os.chroot() is invoked later.
 
452
-        try:
 
453
-            f = open(device_path, "rb", 0)
 
454
-        except EnvironmentError:
 
455
-            raise error("Unable to open /dev/urandom")
 
456
-
 
457
-        # Open a second file descriptor for sanity checking later.
 
458
-        try:
 
459
-            g = open(device_path, "rb", 0)
 
460
-        except EnvironmentError:
 
461
-            raise error("Unable to open /dev/urandom")
 
462
-
 
463
-        # Check that /dev/urandom is a character special device, not a regular file.
 
464
-        st = os.fstat(f.fileno())   # f
 
465
-        if stat.S_ISREG(st.st_mode) or not stat.S_ISCHR(st.st_mode):
 
466
-            raise error("/dev/urandom is not a character special device")
 
467
-
 
468
-        st = os.fstat(g.fileno())   # g
 
469
-        if stat.S_ISREG(st.st_mode) or not stat.S_ISCHR(st.st_mode):
 
470
-            raise error("/dev/urandom is not a character special device")
 
471
-
 
472
-        # Check that /dev/urandom always returns the number of bytes requested
 
473
-        x = f.read(20)
 
474
-        y = g.read(20)
 
475
-        if len(x) != 20 or len(y) != 20:
 
476
-            raise error("Error reading from /dev/urandom: input truncated")
 
477
-
 
478
-        # Check that different reads return different data
 
479
-        if x == y:
 
480
-            raise error("/dev/urandom is broken; returning identical data: %r == %r" % (x, y))
 
481
-
 
482
-        # Close the duplicate file object
 
483
-        g.close()
 
484
-
 
485
-        # Return the first file object
 
486
-        return _RNG(f)
 
487
-
 
488
-    except error:
 
489
-        if f is not None:
 
490
-            f.close()
 
491
-        if g is not None:
 
492
-            g.close()
 
493
-        raise
 
494
-
 
495
-# vim:set ts=4 sw=4 sts=4 expandtab:
 
496
-
 
497
 
 
498
=== removed file 'a/paramiko/rng_win32.py'
 
499
--- a/paramiko/rng_win32.py     2008-05-18 22:45:25 +0000
 
500
+++ b/paramiko/rng_win32.py     1970-01-01 00:00:00 +0000
 
501
@@ -1,121 +0,0 @@
 
502
-#!/usr/bin/python
 
503
-# -*- coding: ascii -*-
 
504
-# Copyright (C) 2008  Dwayne C. Litzenberger <dlitz@dlitz.net>
 
505
-# Copyright (C) 2008  Open Systems Canada Limited
 
506
-#
 
507
-# This file is part of paramiko.
 
508
-#
 
509
-# Paramiko is free software; you can redistribute it and/or modify it under the
 
510
-# terms of the GNU Lesser General Public License as published by the Free
 
511
-# Software Foundation; either version 2.1 of the License, or (at your option)
 
512
-# any later version.
 
513
-#
 
514
-# Paramiko is distrubuted in the hope that it will be useful, but WITHOUT ANY
 
515
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 
516
-# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
 
517
-# details.
 
518
-#
 
519
-# You should have received a copy of the GNU Lesser General Public License
 
520
-# along with Paramiko; if not, write to the Free Software Foundation, Inc.,
 
521
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
522
-
 
523
-class error(Exception):
 
524
-    pass
 
525
-
 
526
-# Try to import the "winrandom" module
 
527
-try:
 
528
-    from Crypto.Util import winrandom as _winrandom
 
529
-except ImportError:
 
530
-    _winrandom = None
 
531
-
 
532
-# Try to import the "urandom" module
 
533
-try:
 
534
-    from os import urandom as _urandom
 
535
-except ImportError:
 
536
-    _urandom = None
 
537
-
 
538
-
 
539
-class _RNG(object):
 
540
-    def __init__(self, readfunc):
 
541
-        self.read = readfunc
 
542
-
 
543
-    def randomize(self):
 
544
-        # According to "Cryptanalysis of the Random Number Generator of the
 
545
-        # Windows Operating System", by Leo Dorrendorf and Zvi Gutterman
 
546
-        # and Benny Pinkas <http://eprint.iacr.org/2007/419>,
 
547
-        # CryptGenRandom only updates its internal state using kernel-provided
 
548
-        # random data every 128KiB of output.
 
549
-        self.read(128*1024)    # discard 128 KiB of output
 
550
-
 
551
-def _open_winrandom():
 
552
-    if _winrandom is None:
 
553
-        raise error("Crypto.Util.winrandom module not found")
 
554
-    
 
555
-    # Check that we can open the winrandom module
 
556
-    try:
 
557
-        r0 = _winrandom.new()
 
558
-        r1 = _winrandom.new()
 
559
-    except Exception, exc:
 
560
-        raise error("winrandom.new() failed: %s" % str(exc), exc)
 
561
-    
 
562
-    # Check that we can read from the winrandom module
 
563
-    try:
 
564
-        x = r0.get_bytes(20)
 
565
-        y = r1.get_bytes(20)
 
566
-    except Exception, exc:
 
567
-        raise error("winrandom get_bytes failed: %s" % str(exc), exc)
 
568
-
 
569
-    # Check that the requested number of bytes are returned
 
570
-    if len(x) != 20 or len(y) != 20:
 
571
-        raise error("Error reading from winrandom: input truncated")
 
572
-
 
573
-    # Check that different reads return different data
 
574
-    if x == y:
 
575
-        raise error("winrandom broken: returning identical data")
 
576
-
 
577
-    return _RNG(r0.get_bytes)
 
578
-
 
579
-def _open_urandom():
 
580
-    if _urandom is None:
 
581
-        raise error("os.urandom function not found")
 
582
-    
 
583
-    # Check that we can read from os.urandom()
 
584
-    try:
 
585
-        x = _urandom(20)
 
586
-        y = _urandom(20)
 
587
-    except Exception, exc:
 
588
-        raise error("os.urandom failed: %s" % str(exc), exc)
 
589
-
 
590
-    # Check that the requested number of bytes are returned
 
591
-    if len(x) != 20 or len(y) != 20:
 
592
-        raise error("os.urandom failed: input truncated")
 
593
-
 
594
-    # Check that different reads return different data
 
595
-    if x == y:
 
596
-        raise error("os.urandom failed: returning identical data")
 
597
-
 
598
-    return _RNG(_urandom)
 
599
-
 
600
-def open_rng_device():
 
601
-    # Try using the Crypto.Util.winrandom module
 
602
-    try:
 
603
-        return _open_winrandom()
 
604
-    except error:
 
605
-        pass
 
606
-
 
607
-    # Several versions of PyCrypto do not contain the winrandom module, but
 
608
-    # Python >= 2.4 has os.urandom, so try to use that.
 
609
-    try:
 
610
-        return _open_urandom()
 
611
-    except error:
 
612
-        pass
 
613
-
 
614
-    # SECURITY NOTE: DO NOT USE Crypto.Util.randpool.RandomPool HERE!
 
615
-    # If we got to this point, RandomPool will silently run with very little
 
616
-    # entropy.  (This is current as of PyCrypto 2.0.1).
 
617
-    # See http://www.lag.net/pipermail/paramiko/2008-January/000599.html
 
618
-    # and http://www.lag.net/pipermail/paramiko/2008-April/000678.html
 
619
-
 
620
-    raise error("Unable to find a strong random entropy source.  You cannot run this software securely under the current configuration.")
 
621
-
 
622
-# vim:set ts=4 sw=4 sts=4 expandtab:
 
623
 
 
624
=== modified file 'a/paramiko/rsakey.py'
 
625
--- a/paramiko/rsakey.py        2009-07-20 02:45:02 +0000
 
626
+++ b/paramiko/rsakey.py        2010-08-02 22:13:08 +0000
 
627
@@ -137,8 +137,7 @@
 
628
         @return: new private key
 
629
         @rtype: L{RSAKey}
 
630
         """
 
631
-        randpool.stir()
 
632
-        rsa = RSA.generate(bits, randpool.get_bytes, progress_func)
 
633
+        rsa = RSA.generate(bits, rng.read, progress_func)
 
634
         key = RSAKey(vals=(rsa.e, rsa.n))
 
635
         key.d = rsa.d
 
636
         key.p = rsa.p
 
637
 
 
638
=== modified file 'a/paramiko/transport.py'
 
639
--- a/paramiko/transport.py     2010-04-25 23:42:45 +0000
 
640
+++ b/paramiko/transport.py     2010-08-02 22:13:08 +0000
 
641
@@ -297,7 +297,7 @@
 
642
         # okay, normal socket-ish flow here...
 
643
         threading.Thread.__init__(self)
 
644
         self.setDaemon(True)
 
645
-        self.randpool = randpool
 
646
+        self.rng = rng
 
647
         self.sock = sock
 
648
         # Python < 2.3 doesn't have the settimeout method - RogerB
 
649
         try:
 
650
@@ -585,7 +585,7 @@
 
651
 
 
652
         @note: This has no effect when used in client mode.
 
653
         """
 
654
-        Transport._modulus_pack = ModulusPack(randpool)
 
655
+        Transport._modulus_pack = ModulusPack(rng)
 
656
         # places to look for the openssh "moduli" file
 
657
         file_list = [ '/etc/ssh/moduli', '/usr/local/etc/moduli' ]
 
658
         if filename is not None:
 
659
@@ -837,10 +837,9 @@
 
660
         """
 
661
         m = Message()
 
662
         m.add_byte(chr(MSG_IGNORE))
 
663
-        randpool.stir()
 
664
         if bytes is None:
 
665
-            bytes = (ord(randpool.get_bytes(1)) % 32) + 10
 
666
-        m.add_bytes(randpool.get_bytes(bytes))
 
667
+            bytes = (ord(rng.read(1)) % 32) + 10
 
668
+        m.add_bytes(rng.read(bytes))
 
669
         self._send_user_message(m)
 
670
 
 
671
     def renegotiate_keys(self):
 
672
@@ -1674,10 +1673,9 @@
 
673
         else:
 
674
             available_server_keys = self._preferred_keys
 
675
 
 
676
-        randpool.stir()
 
677
         m = Message()
 
678
         m.add_byte(chr(MSG_KEXINIT))
 
679
-        m.add_bytes(randpool.get_bytes(16))
 
680
+        m.add_bytes(rng.read(16))
 
681
         m.add_list(self._preferred_kex)
 
682
         m.add_list(available_server_keys)
 
683
         m.add_list(self._preferred_ciphers)
 
684
 
 
685
=== modified file 'a/tests/test_kex.py'
 
686
--- a/tests/test_kex.py 2009-07-20 02:45:02 +0000
 
687
+++ b/tests/test_kex.py 2010-08-02 22:13:08 +0000
 
688
@@ -28,17 +28,15 @@
 
689
 from paramiko import Message
 
690
 
 
691
 
 
692
-class FakeRandpool (object):
 
693
-    def stir(self):
 
694
-        pass
 
695
-    def get_bytes(self, n):
 
696
+class FakeRng (object):
 
697
+    def read(self, n):
 
698
         return chr(0xcc) * n
 
699
 
 
700
 
 
701
 class FakeKey (object):
 
702
     def __str__(self):
 
703
         return 'fake-key'
 
704
-    def sign_ssh_data(self, randpool, H):
 
705
+    def sign_ssh_data(self, rng, H):
 
706
         return 'fake-sig'
 
707
 
 
708
 
 
709
@@ -50,7 +48,7 @@
 
710
 
 
711
 
 
712
 class FakeTransport (object):
 
713
-    randpool = FakeRandpool()
 
714
+    rng = FakeRng()
 
715
     local_version = 'SSH-2.0-paramiko_1.0'
 
716
     remote_version = 'SSH-2.0-lame'
 
717
     local_kex_init = 'local-kex-init'
 
718
 
 
719
=== modified file 'a/tests/test_pkey.py'
 
720
--- a/tests/test_pkey.py        2009-07-20 02:45:02 +0000
 
721
+++ b/tests/test_pkey.py        2010-08-02 22:13:08 +0000
 
722
@@ -23,7 +23,8 @@
 
723
 from binascii import hexlify, unhexlify
 
724
 import StringIO
 
725
 import unittest
 
726
-from paramiko import RSAKey, DSSKey, Message, util, randpool
 
727
+from paramiko import RSAKey, DSSKey, Message, util
 
728
+from paramiko.common import rng
 
729
 
 
730
 # from openssh's ssh-keygen
 
731
 PUB_RSA = 'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA049W6geFpmsljTwfvI1UmKWWJPNFI74+vNKTk4dmzkQY2yAMs6FhlvhlI8ysU4oj71ZsRYMecHbBbxdN79+JRFVYTKaLqjwGENeTd+yv4q+V2PvZv3fLnzApI3l7EJCqhWwJUHJ1jAkZzqDx0tyOL4uoZpww3nmE0kb3y21tH4c='
 
732
@@ -151,7 +152,7 @@
 
733
     def test_8_sign_rsa(self):
 
734
         # verify that the rsa private key can sign and verify
 
735
         key = RSAKey.from_private_key_file('tests/test_rsa.key')
 
736
-        msg = key.sign_ssh_data(randpool, 'ice weasels')
 
737
+        msg = key.sign_ssh_data(rng, 'ice weasels')
 
738
         self.assert_(type(msg) is Message)
 
739
         msg.rewind()
 
740
         self.assertEquals('ssh-rsa', msg.get_string())
 
741
@@ -164,7 +165,7 @@
 
742
     def test_9_sign_dss(self):
 
743
         # verify that the dss private key can sign and verify
 
744
         key = DSSKey.from_private_key_file('tests/test_dss.key')
 
745
-        msg = key.sign_ssh_data(randpool, 'ice weasels')
 
746
+        msg = key.sign_ssh_data(rng, 'ice weasels')
 
747
         self.assert_(type(msg) is Message)
 
748
         msg.rewind()
 
749
         self.assertEquals('ssh-dss', msg.get_string())
 
750
@@ -178,12 +179,12 @@
 
751
     
 
752
     def test_A_generate_rsa(self):
 
753
         key = RSAKey.generate(1024)
 
754
-        msg = key.sign_ssh_data(randpool, 'jerri blank')
 
755
+        msg = key.sign_ssh_data(rng, 'jerri blank')
 
756
         msg.rewind()
 
757
         self.assert_(key.verify_ssh_sig('jerri blank', msg))
 
758
 
 
759
     def test_B_generate_dss(self):
 
760
         key = DSSKey.generate(1024)
 
761
-        msg = key.sign_ssh_data(randpool, 'jerri blank')
 
762
+        msg = key.sign_ssh_data(rng, 'jerri blank')
 
763
         msg.rewind()
 
764
         self.assert_(key.verify_ssh_sig('jerri blank', msg))
 
765
 
 
766
=== modified file 'a/tests/test_util.py'
 
767
--- a/tests/test_util.py        2009-07-20 02:45:02 +0000
 
768
+++ b/tests/test_util.py        2010-08-02 22:13:08 +0000
 
769
@@ -147,8 +147,8 @@
 
770
             os.unlink('hostfile.temp')
 
771
 
 
772
     def test_6_random(self):
 
773
-        from paramiko.common import randpool
 
774
+        from paramiko.common import rng
 
775
         # just verify that we can pull out 32 bytes and not get an exception.
 
776
-        x = randpool.get_bytes(32)
 
777
+        x = rng.read(32)
 
778
         self.assertEquals(len(x), 32)
 
779
         
 
780