Skip to content

Commit 102c562

Browse files
committed
A real fix for the problem where:
import random would result in every call to random() returning the same value in the web interface. While cgi/client.py:Client::__init.py__ was calling random.seed(), on most systems random was SystemRandom and not the default random. As a result the random as you would get from: import random was never being seeded. I added a function to access and seed the random bound instance of random.Random that is called during init. This fixes all three places where I saw the broken randomness. It should also fix: http://psf.upfronthosting.co.za/roundup/meta/issue644 I also removed the prior code that would bail if systemRandom was not available.
1 parent 5a16726 commit 102c562

File tree

7 files changed

+27
-67
lines changed

7 files changed

+27
-67
lines changed

roundup/cgi/actions.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
1-
import re, cgi, time, csv, codecs
1+
import re, cgi, time, random, csv, codecs
22
from io import BytesIO
33

4-
try:
5-
# Use the cryptographic source of randomness if available
6-
from random import SystemRandom
7-
random=SystemRandom()
8-
except ImportError:
9-
raise
10-
from random import Random
11-
random=Random()
12-
134
from roundup import hyperdb, token, date, password
145
from roundup.actions import Action as BaseAction
156
from roundup.i18n import _

roundup/cgi/client.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@
1717
random=SystemRandom()
1818
logger.debug("Importing good random generator")
1919
except ImportError:
20-
raise
21-
from random import Random
22-
random=Random()
20+
from random import random
2321
logger.warning("**SystemRandom not available. Using poor random generator")
2422

2523
try:
@@ -81,6 +79,19 @@ def add_message(msg_list, msg, escape=True):
8179
The tracker maintainers have been notified of the problem.</p>
8280
</body></html>"""
8381

82+
def seed_pseudorandom():
83+
'''A function to seed the default pseudorandom random number generator
84+
which is used to (at minimum):
85+
* generate part of email message-id
86+
* generate OTK for password reset
87+
* generate the temp recovery password
88+
89+
This function limits the scope of the 'import random' call
90+
as the random identifier is used throughout the code and
91+
can refer to SystemRandom.
92+
'''
93+
import random
94+
random.seed()
8495

8596
class LiberalCookie(SimpleCookie):
8697
""" Python's SimpleCookie throws an exception if the cookie uses invalid
@@ -307,8 +318,14 @@ class Client:
307318
)
308319

309320
def __init__(self, instance, request, env, form=None, translator=None):
310-
# re-seed the random number generator
321+
# re-seed the random number generator. Is this is an instance of
322+
# random.SystemRandom it has no effect.
311323
random.seed()
324+
# So we also seed the pseudorandom random source obtained from
325+
# import random
326+
# to make sure that every forked copy of the client will return
327+
# new random numbers.
328+
seed_pseudorandom()
312329
self.start = time.time()
313330
self.instance = instance
314331
self.request = request

roundup/cgi/templating.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,7 @@
3636
from random import SystemRandom
3737
random=SystemRandom()
3838
except ImportError:
39-
raise
40-
from random import Random
41-
random=Random()
42-
39+
from random import random
4340
try:
4441
import cPickle as pickle
4542
except ImportError:

roundup/mailgw.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -95,19 +95,10 @@ class node. Any parts of other types are each stored in separate files
9595
__docformat__ = 'restructuredtext'
9696

9797
import string, re, os, mimetools, cStringIO, smtplib, socket, binascii, quopri
98-
import time, sys, logging
98+
import time, random, sys, logging
9999
import traceback
100100
import email.utils
101101

102-
try:
103-
# Use the cryptographic source of randomness if available
104-
from random import SystemRandom
105-
random=SystemRandom()
106-
except ImportError:
107-
raise
108-
from random import Random
109-
random=Random()
110-
111102
from anypy.email_ import decode_header
112103

113104
from roundup import configuration, hyperdb, date, password, exceptions

roundup/password.py

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,11 @@
1919
"""
2020
__docformat__ = 'restructuredtext'
2121

22-
import re, string
22+
import re, string, random
2323
import os
2424
from base64 import b64encode, b64decode
2525
from hashlib import md5, sha1
2626

27-
try:
28-
# Use the cryptographic source of randomness if available
29-
from random import SystemRandom
30-
random=SystemRandom()
31-
except ImportError:
32-
raise
33-
from random import Random
34-
random=Random()
35-
3627
try:
3728
import crypt
3829
except ImportError:
@@ -372,13 +363,6 @@ def test():
372363
assert 'sekrit' == p
373364
assert 'not sekrit' != p
374365

375-
376-
print random.randrange(36, 52)
377-
# this seems to return the save password every time
378-
# when run inside a roundup daemon.
379-
# but it tests out ok. I don't know why. -- rouilj
380-
print generatePassword()
381-
382366
if __name__ == '__main__':
383367
test()
384368

roundup/roundupdb.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,7 @@
2020
"""
2121
__docformat__ = 'restructuredtext'
2222

23-
import re, os, smtplib, socket, time
24-
25-
try:
26-
# Use the cryptographic source of randomness if available
27-
from random import SystemRandom
28-
random=SystemRandom()
29-
except ImportError:
30-
raise
31-
from random import Random
32-
random=Random()
33-
23+
import re, os, smtplib, socket, time, random
3424
import cStringIO, base64, mimetypes
3525
import os.path
3626
import logging

roundup/scripts/roundup_server.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -88,17 +88,7 @@
8888

8989
def auto_ssl():
9090
print _('WARNING: generating temporary SSL certificate')
91-
import OpenSSL
92-
93-
try:
94-
# Use the cryptographic source of randomness if available
95-
from random import SystemRandom
96-
random=SystemRandom()
97-
except ImportError:
98-
raise
99-
from random import Random
100-
random=Random()
101-
91+
import OpenSSL, random
10292
pkey = OpenSSL.crypto.PKey()
10393
pkey.generate_key(OpenSSL.crypto.TYPE_RSA, 768)
10494
cert = OpenSSL.crypto.X509()

0 commit comments

Comments
 (0)