Skip to content
This repository has been archived by the owner on Apr 10, 2023. It is now read-only.

Commit

Permalink
use system random
Browse files Browse the repository at this point in the history
  • Loading branch information
davisagli committed Nov 26, 2012
1 parent cda933f commit 551b0eb
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGES.txt
Expand Up @@ -4,6 +4,10 @@ Changelog
2.0.10 (unreleased)
-------------------

- Use system random when available. This is part of the fix for
https://plone.org/products/plone/security/advisories/20121106/24
[davisagli]

- registered_notify_template.pt: show login name instead of user id.
Normally this is the same, but this is not necessarily true when
using the email address as login name.
Expand Down
9 changes: 5 additions & 4 deletions Products/PasswordResetTool/PasswordResetTool.py
Expand Up @@ -25,10 +25,11 @@
except ImportError:
# Avoid hard dependency on Plone (4.0)
get_member_by_login_name = None
from Products.PasswordResetTool import django_random

from interfaces.portal_password_reset import portal_password_reset as IPWResetTool

import datetime, time, random, socket
import datetime, time, socket
from DateTime import DateTime
from zope.interface import implements

Expand Down Expand Up @@ -291,13 +292,13 @@ def uniqueString(self, userid):
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/213761
# by Carl Free Jr
t = long( time.time() * 1000 )
r = long( random.random()*100000000000000000L )
r = django_random.get_random_string(64)
try:
a = socket.gethostbyname( socket.gethostname() )
except:
# if we can't get a network address, just imagine one
a = random.random()*100000000000000000L
data = str(t)+' '+str(r)+' '+str(a)#+' '+str(args)
a = django_crypto.get_random_string(64)
data = str(t) + ' ' + str(r) + ' ' + str(a)
data = md5(data).hexdigest()
return str(data)

Expand Down
73 changes: 73 additions & 0 deletions Products/PasswordResetTool/django_random.py
@@ -0,0 +1,73 @@
"""
Copyright (c) Django Software Foundation and individual contributors.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of Django nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""

import random
try:
random = random.SystemRandom()
using_sysrandom = True
except NotImplementedError:
using_sysrandom = False

try:
from hashlib import sha256 as sha
except ImportError:
from sha import sha

import time


# generated when process started, hard to guess
SECRET = random.randint(0, 1000000)


def get_random_string(length=12,
allowed_chars='abcdefghijklmnopqrstuvwxyz'
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'):
"""
Returns a securely generated random string.
The default length of 12 with the a-z, A-Z, 0-9 character set returns
a 71-bit value. log_2((26+26+10)^12) =~ 71 bits
"""
if not using_sysrandom:
# This is ugly, and a hack, but it makes things better than
# the alternative of predictability. This re-seeds the PRNG
# using a value that is hard for an attacker to predict, every
# time a random string is required. This may change the
# properties of the chosen random sequence slightly, but this
# is better than absolute predictability.
random.seed(
sha(
"%s%s%s" % (
random.getstate(),
time.time(),
SECRET)
).digest())
return ''.join([random.choice(allowed_chars) for i in range(length)])
33 changes: 33 additions & 0 deletions docs/LICENSE.txt
Expand Up @@ -22,3 +22,36 @@ Portions Copyright (c) 2001-2003 George A. Runyan Jr., Alexander Limi and Vidar
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA


django_random
=============

Code in django_random.py is distributed under this license:

Copyright (c) Django Software Foundation and individual contributors.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

3. Neither the name of Django nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

0 comments on commit 551b0eb

Please sign in to comment.