mirror of
https://github.com/haiwen/seahub.git
synced 2025-04-26 18:40:53 +00:00
fix Use of a broken or weak cryptographic hashing (#7671)
Co-authored-by: lian <imwhatiam123@gmail.com>
This commit is contained in:
parent
c8026ddb6c
commit
5eb303c76b
@ -252,7 +252,7 @@ class ResetPasswordView(APIView):
|
||||
user.save()
|
||||
|
||||
if not request.session.is_empty():
|
||||
# update session auth hash
|
||||
# invalidate all active sessions after change password.
|
||||
update_session_auth_hash(request, request.user)
|
||||
|
||||
return Response({'success': True})
|
||||
|
@ -1,46 +1,15 @@
|
||||
# Copyright (c) 2012-2016 Seafile Ltd.
|
||||
import hashlib
|
||||
import logging
|
||||
from registration.signals import user_deleted
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
from django.dispatch import receiver
|
||||
from django.utils.encoding import smart_str
|
||||
from django.db.models.manager import EmptyManager
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
UNUSABLE_PASSWORD = '!' # This will never be a valid hash
|
||||
|
||||
|
||||
def get_hexdigest(algorithm, salt, raw_password):
|
||||
"""
|
||||
Returns a string of the hexdigest of the given plaintext password and salt
|
||||
using the given algorithm ('md5', 'sha1' or 'crypt').
|
||||
"""
|
||||
raw_password, salt = smart_str(raw_password).encode('utf-8'), smart_str(salt).encode('utf-8')
|
||||
if algorithm == 'crypt':
|
||||
try:
|
||||
import crypt
|
||||
except ImportError:
|
||||
raise ValueError('"crypt" password algorithm not supported in this environment')
|
||||
return crypt.crypt(raw_password, salt)
|
||||
|
||||
if algorithm == 'md5':
|
||||
return hashlib.md5(salt + raw_password).hexdigest()
|
||||
elif algorithm == 'sha1':
|
||||
return hashlib.sha1(salt + raw_password).hexdigest()
|
||||
raise ValueError("Got unknown password algorithm type in password.")
|
||||
|
||||
|
||||
def check_password(raw_password, enc_password):
|
||||
"""
|
||||
Returns a boolean of whether the raw_password was correct. Handles
|
||||
encryption formats behind the scenes.
|
||||
"""
|
||||
algo, salt, hsh = enc_password.split('$')
|
||||
return hsh == get_hexdigest(algo, salt, raw_password)
|
||||
|
||||
|
||||
class SiteProfileNotAvailable(Exception):
|
||||
pass
|
||||
|
||||
|
@ -670,13 +670,6 @@ class User(object):
|
||||
Returns a boolean of whether the raw_password was correct. Handles
|
||||
encryption formats behind the scenes.
|
||||
"""
|
||||
# Backwards-compatibility check. Older passwords won't include the
|
||||
# algorithm or salt.
|
||||
|
||||
# if '$' not in self.password:
|
||||
# is_correct = (self.password == \
|
||||
# get_hexdigest('sha1', '', raw_password))
|
||||
# return is_correct
|
||||
return (ccnet_threaded_rpc.validate_emailuser(self.username, raw_password) == 0)
|
||||
|
||||
def set_unusable_password(self):
|
||||
|
@ -11,6 +11,9 @@ PASSWORD_HASH_KEY = getattr(settings, 'PASSWORD_SESSION_PASSWORD_HASH_KEY', 'pas
|
||||
def get_password_hash(user):
|
||||
"""Returns a string of crypted password hash"""
|
||||
password = user.enc_password or ''
|
||||
# To achieve "invalidate all active sessions after change password",
|
||||
# a hash value generated based on the user password is stored in the session,
|
||||
# and compare it for each request in the MIDDLEWARE.
|
||||
return md5(
|
||||
md5(password.encode()).hexdigest().encode() + settings.SECRET_KEY.encode()
|
||||
).hexdigest()
|
||||
|
@ -115,7 +115,10 @@ class RegistrationManager(models.Manager):
|
||||
username = user.username
|
||||
if isinstance(username, str):
|
||||
username = username.encode('utf-8')
|
||||
activation_key = hashlib.sha1(salt+username).hexdigest()
|
||||
|
||||
# Take the first 16 character to avoid errors.
|
||||
# (1406, "Data too long for column 'activation_key' at row 1")
|
||||
activation_key = hashlib.sha256(salt+username).hexdigest()[:16]
|
||||
return self.create(emailuser_id=user.id,
|
||||
activation_key=activation_key)
|
||||
|
||||
|
@ -1,91 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
# Copyright (c) 2012-2016 Seafile Ltd.
|
||||
|
||||
import sqlite3
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import hashlib
|
||||
import getpass
|
||||
|
||||
# Get .ccnet directory from argument or user input
|
||||
if len(sys.argv) >= 2:
|
||||
ccnet_dir = sys.argv[1]
|
||||
else:
|
||||
home_dir = os.path.join(os.path.expanduser('~'), '.ccnet')
|
||||
ccnet_dir = input("Enter ccnet directory:(leave blank for %s) " % home_dir)
|
||||
if not ccnet_dir:
|
||||
ccnet_dir = home_dir
|
||||
|
||||
# Test usermgr.db exists
|
||||
usermgr_db = os.path.join(ccnet_dir, 'PeerMgr/usermgr.db')
|
||||
if not os.path.exists(usermgr_db):
|
||||
print('%s DOES NOT exist. FAILED' % usermgr_db)
|
||||
sys.exit(1)
|
||||
|
||||
# Connect db
|
||||
conn = sqlite3.connect(usermgr_db)
|
||||
|
||||
# Get cursor
|
||||
c = conn.cursor()
|
||||
|
||||
# Check whether admin user exists
|
||||
sql = "SELECT email FROM EmailUser WHERE is_staff = 1"
|
||||
try:
|
||||
c.execute(sql)
|
||||
except sqlite3.Error as e:
|
||||
print("An error orrured:", e.args[0])
|
||||
sys.exit(1)
|
||||
|
||||
staff_list = c.fetchall()
|
||||
if staff_list:
|
||||
print("Admin is already in database. Email as follows: ")
|
||||
print('--------------------')
|
||||
for e in staff_list:
|
||||
print(e[0])
|
||||
print('--------------------')
|
||||
choice = input('Previous admin would be deleted, would you like to continue?[y/n] ')
|
||||
if choice == 'y':
|
||||
sql = "DELETE FROM EmailUser WHERE is_staff = 1"
|
||||
try:
|
||||
c.execute(sql)
|
||||
except sqlite3.Error as e:
|
||||
print("An error orrured:", e.args[0])
|
||||
sys.exit(1)
|
||||
else:
|
||||
print('Previous admin is deleted.')
|
||||
else:
|
||||
conn.close()
|
||||
sys.exit(0)
|
||||
|
||||
# Create admin user
|
||||
choice = input('Would you like to create admin user?[y/n]')
|
||||
if choice != 'y':
|
||||
conn.close()
|
||||
sys.exit(0)
|
||||
|
||||
username = input('E-mail address:')
|
||||
passwd = getpass.getpass('Password:')
|
||||
passwd2 = getpass.getpass('Password (again):')
|
||||
if passwd != passwd2:
|
||||
print("Two passwords NOT same.")
|
||||
sys.exit(1)
|
||||
|
||||
mySha1 = hashlib.sha1()
|
||||
mySha1.update(passwd.encode('utf-8'))
|
||||
enc_passwd = mySha1.hexdigest()
|
||||
sql = "INSERT INTO EmailUser(email, passwd, is_staff, is_active, ctime) VALUES ('%s', '%s', 1, 1, '%d');" % (username, enc_passwd, time.time()*1000000)
|
||||
try:
|
||||
c = conn.cursor()
|
||||
c.execute(sql)
|
||||
conn.commit()
|
||||
except sqlite3.Error as e:
|
||||
print("An error occured:", e.args[0])
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("Admin user created successfully.")
|
||||
|
||||
# Close db
|
||||
conn.close()
|
||||
|
Loading…
Reference in New Issue
Block a user