Skip to content

Commit

Permalink
Encrypt passwords using bcrypt, keep sha256 for backwards compatibility
Browse files Browse the repository at this point in the history
The number of rounds can be specified by BCRYPT_ROUNDS environment variable. The default value is 14, as it takes 600 ms on my machine.
As we currently only support bcrypt and plain sha256 hashes, we can distinguish them by the leading '$' of bcrypt hashes.
Upgrading hashes on login is not yet implemented.
  • Loading branch information
Jonny007-MKD committed Jan 8, 2023
1 parent 6ca9cd5 commit 4373f43
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 8 deletions.
14 changes: 9 additions & 5 deletions app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from flask_login import LoginManager
from flask_mail import Mail
from secrets import token_urlsafe
from passlib.hash import bcrypt
import hashlib
import os
import click
Expand Down Expand Up @@ -59,12 +60,14 @@

# Security - Generate GLAUTH compatible password hashs
def generate_password_hash(password):
return hashlib.sha256(password.encode('utf-8')).hexdigest()
return bcrypt.using(rounds=app.config['BCRYPT_ROUNDS']).hash(password)

def check_password_hash(hash, password):
if (hash != hashlib.sha256(password.encode('utf-8')).hexdigest()):
return False
return True
if not hash.startswith('$'): # plain SHA256 hashes were stored like this
return hash == hashlib.sha256(password.encode('utf-8')).hexdigest()
# TODO: Re-hash password with bcrypt and replace stored hash

return bcrypt.verify(password, hash)

from app import routes, models, glauth, adminview, errors

Expand All @@ -76,4 +79,5 @@ def createdbdata():
click.echo('Creating Example DB')
models.create_basic_db()
else:
app.logger.info('Data in DB allready exists.')
app.logger.info('Data in DB allready exists.')

6 changes: 4 additions & 2 deletions app/glauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ def create_glauth_config():
new_config += " mail = \"{}\"\n".format(user.mail)
new_config += " uidnumber = {}\n".format(user.unixid)
new_config += " primarygroup = {}\n".format(user.primarygroup)
new_config += " passsha256 = \"{}\"\n".format(user.password_hash)
if not user.password_hash.startswith('$'): # SHA256 hashes were stored like this
new_config += " passsha256 = \"{}\"\n".format(user.password_hash)
else: # bcrypt hashes have to be put into the config in hex representation
new_config += " passbcrypt = \"{}\"\n".format(user.password_hash.encode("utf-8").hex())
if len(user.othergroups) > 0:
new_config += " otherGroups = [ {} ]\n".format(",".join(str(group.unixid) for group in user.othergroups))
if not user.is_active:
Expand All @@ -74,4 +77,3 @@ def create_glauth_config():
f.write(new_config)
f.close()


9 changes: 8 additions & 1 deletion config.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import os
basedir = os.path.abspath(os.path.dirname(__file__))

def optional_str_to_int(s):
if s is None: return None
return int(s)


class Config(object):
APPNAME = os.environ.get('APPNAME') or 'Glauth UI'
ORGANISATION = os.environ.get('ORGANISATION') or 'Glauth UI - Team'
SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess'
BCRYPT_ROUNDS = optional_str_to_int(os.environ.get('BCRYPT_ROUNDS')) or 14
ADMIN_GROUP = os.environ.get('ADMIN_GROUP') or 'glauth_admin'

# MAIL Config
Expand All @@ -25,4 +31,5 @@ class Config(object):
os.path.join(basedir, 'db', 'config.cfg')

# FLASK ADMIN STUFF
FLASK_ADMIN_FLUID_LAYOUT = False
FLASK_ADMIN_FLUID_LAYOUT = False

1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ python-dotenv==0.19.2
SQLAlchemy==1.4.29
Werkzeug==2.0.2
WTForms==3.0.1
passlib==1.7.4

0 comments on commit 4373f43

Please sign in to comment.