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