Fixed #95 -- Added SECRET_KEY setting instead of hard-coding keys that are shared for every Django installation. 'django-admin.py startproject' now creates a random SECRET_KEY. The auth and comments modules, and the admin middleware, all use SECRET_KEY now, instead of hard-coded values.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@230 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2005-07-20 00:37:45 +00:00
parent 43538e78eb
commit 897d24b220
6 changed files with 32 additions and 21 deletions

View File

@ -340,15 +340,24 @@ def _start_helper(app_or_project, name, directory, other_name=''):
def startproject(project_name, directory): def startproject(project_name, directory):
"Creates a Django project for the given project_name in the given directory." "Creates a Django project for the given project_name in the given directory."
from whrandom import choice
_start_helper('project', project_name, directory) _start_helper('project', project_name, directory)
# Populate TEMPLATE_DIRS for the admin templates, based on where Django is # Populate TEMPLATE_DIRS for the admin templates, based on where Django is
# installed. # installed.
settings_file = os.path.join(directory, project_name, 'settings/admin.py') admin_settings_file = os.path.join(directory, project_name, 'settings/admin.py')
settings_contents = open(settings_file, 'r').read() settings_contents = open(admin_settings_file, 'r').read()
fp = open(settings_file, 'w') fp = open(admin_settings_file, 'w')
settings_contents = re.sub(r'(?s)\b(TEMPLATE_DIRS\s*=\s*\()(.*?)\)', "\\1\n '%s',\\2)" % ADMIN_TEMPLATE_DIR, settings_contents) settings_contents = re.sub(r'(?s)\b(TEMPLATE_DIRS\s*=\s*\()(.*?)\)', "\\1\n '%s',\\2)" % ADMIN_TEMPLATE_DIR, settings_contents)
fp.write(settings_contents) fp.write(settings_contents)
fp.close() fp.close()
# Create a random SECRET_KEY hash, and put it in the main settings.
main_settings_file = os.path.join(directory, project_name, 'settings/main.py')
settings_contents = open(main_settings_file, 'r').read()
fp = open(main_settings_file, 'w')
secret_key = ''.join([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)])
settings_contents = re.sub(r"(?<=SECRET_KEY = ')'", secret_key + "'", settings_contents)
fp.write(settings_contents)
fp.close()
startproject.help_doc = "Creates a Django project directory structure for the given project name in the current directory." startproject.help_doc = "Creates a Django project directory structure for the given project name in the current directory."
startproject.args = "[projectname]" startproject.args = "[projectname]"

View File

@ -96,6 +96,11 @@ ADMIN_FOR = []
IGNORABLE_404_STARTS = ('/cgi-bin/', '/_vti_bin', '/_vti_inf') IGNORABLE_404_STARTS = ('/cgi-bin/', '/_vti_bin', '/_vti_inf')
IGNORABLE_404_ENDS = ('mail.pl', 'mailform.pl', 'mail.cgi', 'mailform.cgi', 'favicon.ico', '.php') IGNORABLE_404_ENDS = ('mail.pl', 'mailform.pl', 'mail.cgi', 'mailform.cgi', 'favicon.ico', '.php')
# A secret key for this particular Django installation. Used in secret-key
# hashing algorithms. Set this in your settings, or Django will complain
# loudly.
SECRET_KEY = ''
############## ##############
# MIDDLEWARE # # MIDDLEWARE #
############## ##############

View File

@ -26,6 +26,9 @@ MEDIA_ROOT = ''
# Example: "http://media.lawrence.com" # Example: "http://media.lawrence.com"
MEDIA_URL = '' MEDIA_URL = ''
# Make this unique, and don't share it with anybody.
SECRET_KEY = ''
ROOT_URLCONF = '{{ project_name }}.settings.urls.main' ROOT_URLCONF = '{{ project_name }}.settings.urls.main'
TEMPLATE_DIRS = ( TEMPLATE_DIRS = (

View File

@ -31,9 +31,6 @@ class Comment(meta.Model):
meta.ForeignKey(core.Site), meta.ForeignKey(core.Site),
) )
module_constants = { module_constants = {
# used as shared secret between comment form and comment-posting script
'COMMENT_SALT': 'ijw2f3_MRS_PIGGY_LOVES_KERMIT_avo#*5vv0(23j)(*',
# min. and max. allowed dimensions for photo resizing (in pixels) # min. and max. allowed dimensions for photo resizing (in pixels)
'MIN_PHOTO_DIMENSION': 5, 'MIN_PHOTO_DIMENSION': 5,
'MAX_PHOTO_DIMENSION': 1000, 'MAX_PHOTO_DIMENSION': 1000,
@ -123,8 +120,9 @@ class Comment(meta.Model):
'pa,ra') and target (something like 'lcom.eventtimes:5157'). Used to 'pa,ra') and target (something like 'lcom.eventtimes:5157'). Used to
validate that submitted form options have not been tampered-with. validate that submitted form options have not been tampered-with.
""" """
from django.conf.settings import SECRET_KEY
import md5 import md5
return md5.new(options + photo_options + rating_options + target + COMMENT_SALT).hexdigest() return md5.new(options + photo_options + rating_options + target + SECRET_KEY).hexdigest()
def _module_get_rating_options(rating_string): def _module_get_rating_options(rating_string):
""" """

View File

@ -5,9 +5,7 @@ from django.models.auth import sessions, users
from django.views.registration import passwords from django.views.registration import passwords
import base64, md5 import base64, md5
import cPickle as pickle import cPickle as pickle
from django.conf.settings import SECRET_KEY
# secret used in pickled data to guard against tampering
TAMPER_SECRET = '09VJWE9_RIZZO_j0jwfe09j'
ERROR_MESSAGE = "Please enter a correct username and password. Note that both fields are case-sensitive." ERROR_MESSAGE = "Please enter a correct username and password. Note that both fields are case-sensitive."
@ -108,13 +106,13 @@ class AdminUserRequired:
def encode_post_data(post_data): def encode_post_data(post_data):
pickled = pickle.dumps(post_data) pickled = pickle.dumps(post_data)
pickled_md5 = md5.new(pickled + TAMPER_SECRET).hexdigest() pickled_md5 = md5.new(pickled + SECRET_KEY).hexdigest()
return base64.encodestring(pickled + pickled_md5) return base64.encodestring(pickled + pickled_md5)
def decode_post_data(encoded_data): def decode_post_data(encoded_data):
encoded_data = base64.decodestring(encoded_data) encoded_data = base64.decodestring(encoded_data)
pickled, tamper_check = encoded_data[:-32], encoded_data[-32:] pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
if md5.new(pickled + TAMPER_SECRET).hexdigest() != tamper_check: if md5.new(pickled + SECRET_KEY).hexdigest() != tamper_check:
from django.core.exceptions import SuspiciousOperation from django.core.exceptions import SuspiciousOperation
raise SuspiciousOperation, "User may have tampered with session cookie." raise SuspiciousOperation, "User may have tampered with session cookie."
return pickle.loads(pickled) return pickle.loads(pickled)

View File

@ -182,10 +182,6 @@ class Session(meta.Model):
meta.DateTimeField('start_time', 'start time', auto_now=True), meta.DateTimeField('start_time', 'start time', auto_now=True),
) )
module_constants = { module_constants = {
# Used for providing pseudo-entropy in creating random session strings.
'SESSION_SALT': 'ijw2f3_MUPPET_avo#*5)(*',
# Secret used in cookie to guard against cookie tampering.
'TAMPER_SECRET': 'lj908_PIGGY_j0vajeawej-092j3f',
'TEST_COOKIE_NAME': 'testcookie', 'TEST_COOKIE_NAME': 'testcookie',
'TEST_COOKIE_VALUE': 'worked', 'TEST_COOKIE_VALUE': 'worked',
} }
@ -195,26 +191,28 @@ class Session(meta.Model):
def get_cookie(self): def get_cookie(self):
"Returns a tuple of the cookie name and value for this session." "Returns a tuple of the cookie name and value for this session."
from django.conf.settings import AUTH_SESSION_COOKIE, SECRET_KEY
import md5 import md5
from django.conf.settings import AUTH_SESSION_COOKIE return AUTH_SESSION_COOKIE, self.session_md5 + md5.new(self.session_md5 + SECRET_KEY + 'auth').hexdigest()
return AUTH_SESSION_COOKIE, self.session_md5 + md5.new(self.session_md5 + TAMPER_SECRET).hexdigest()
def _module_create_session(user_id): def _module_create_session(user_id):
"Registers a session and returns the session_md5." "Registers a session and returns the session_md5."
from django.conf.settings import SECRET_KEY
import md5, random, sys import md5, random, sys
# The random module is seeded when this Apache child is created. # The random module is seeded when this Apache child is created.
# Use person_id and SESSION_SALT as added salt. # Use person_id and SECRET_KEY as added salt.
session_md5 = md5.new(str(random.randint(user_id, sys.maxint - 1)) + SESSION_SALT).hexdigest() session_md5 = md5.new(str(random.randint(user_id, sys.maxint - 1)) + SECRET_KEY).hexdigest()
s = Session(None, user_id, session_md5, None) s = Session(None, user_id, session_md5, None)
s.save() s.save()
return s return s
def _module_get_session_from_cookie(session_cookie_string): def _module_get_session_from_cookie(session_cookie_string):
from django.conf.settings import SECRET_KEY
import md5 import md5
if not session_cookie_string: if not session_cookie_string:
raise SessionDoesNotExist raise SessionDoesNotExist
session_md5, tamper_check = session_cookie_string[:32], session_cookie_string[32:] session_md5, tamper_check = session_cookie_string[:32], session_cookie_string[32:]
if md5.new(session_md5 + TAMPER_SECRET).hexdigest() != tamper_check: if md5.new(session_md5 + SECRET_KEY + 'auth').hexdigest() != tamper_check:
raise SuspiciousOperation, "User may have tampered with session cookie." raise SuspiciousOperation, "User may have tampered with session cookie."
return get_object(session_md5__exact=session_md5, select_related=True) return get_object(session_md5__exact=session_md5, select_related=True)