Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Version 1.1.0
Signed-off-by: Chris Warrick <kwpolska@gmail.com>
  • Loading branch information
Kwpolska committed Jan 27, 2015
1 parent eae642f commit 6075474
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 12 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.rst
Expand Up @@ -2,9 +2,12 @@
Appendix A. Changelog
=====================

master
v1.1.0
------

* Changed hashing mechanism to sha256 + bcrypt.
Hashes will be fixed automatically on first login of each user.
* Added ``passlib`` dependency.
* rqworker queue is now named ``coil`` (was ``default``)
* add trailing slashes to all URLs
* use ``url_for()``
Expand Down
4 changes: 3 additions & 1 deletion coil/init.py
Expand Up @@ -44,8 +44,10 @@ def write_users(dburl):
data = {
'username': 'admin',
'realname': 'Website Administrator',
'email': 'coil@example.com',
'password':
'$2a$12$.qMCcA2uOo0BKkDtEF/bueYtHjcdPBmfEdpxtktRwRTgsR7ZVTWmW',
r'$bcrypt-sha256$2a,12$NNtd2TC9mZO6.EvLwEwlLO$axojD34/iE8x'
r'QitQnCCOGPhofgmjNdq',
}

for p in PERMISSIONS:
Expand Down
59 changes: 49 additions & 10 deletions coil/web.py
Expand Up @@ -43,7 +43,7 @@
url_for)
from flask.ext.login import (LoginManager, login_required, login_user,
logout_user, current_user, make_secure_token)
from flask.ext.bcrypt import Bcrypt
from passlib.hash import bcrypt_sha256
from coil.utils import USER_FIELDS, PERMISSIONS, PERMISSIONS_E, SiteProxy
from coil.forms import (LoginForm, NewPostForm, NewPageForm, DeleteForm,
UserDeleteForm, UserEditForm, AccountForm,
Expand Down Expand Up @@ -78,7 +78,6 @@ def configure_site():
_dn = nikola.__main__.main([])
_dn.sub_cmds = _dn.get_commands()
_site = _dn.nikola
app.config['BCRYPT_LOG_ROUNDS'] = 12
app.config['NIKOLA_ROOT'] = os.getcwd()
app.config['DEBUG'] = False

Expand Down Expand Up @@ -183,26 +182,45 @@ def configure_site():


def password_hash(password):
"""Hash the password, using bcrypt.
"""Hash the password, using bcrypt+sha256.
.. versionchanged:: 1.1.0
:param str password: Password in plaintext
:return: password hash
:rtype: str
"""
return bcrypt.generate_password_hash(password)
return bcrypt_sha256.encrypt(password)


def check_password(pwdhash, password):
"""Check the password hash from :func:`password_hash`.
.. versionchanged:: 1.1.0
:param str pwdhash: Hash from :func:`password_hash` to check
:param str password: Password in plaintext
:return: password match
:rtype: bool
"""
return bcrypt.check_password_hash(pwdhash, password)
return bcrypt_sha256.verify(password, pwdhash)


def check_old_password(pwdhash, password):
"""Check the old password hash from :func:`password_hash`.
.. versionadded:: 1.1.0
:param str pwdhash: Hash from :func:`password_hash` to check
:param str password: Password in plaintext
:return: password match
:rtype: bool
"""
from flask.ext.bcrypt import Bcrypt
app.config['BCRYPT_LOG_ROUNDS'] = 12
bcrypt = Bcrypt(app)
return bcrypt.check_password_hash(pwdhash, password)

def generate_menu():
"""Generate ``menu`` with the rebuild link.
Expand Down Expand Up @@ -355,7 +373,6 @@ def log_request(resp):
app.http_logger.error(l)
return resp

bcrypt = Bcrypt(app)
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.unauthorized_callback = _unauthorized
Expand Down Expand Up @@ -476,13 +493,28 @@ def login():
alert = 'Invalid credentials.'
code = 401
else:
if check_password(user.password,
request.form['password']) and user.is_active:
try:
pwd_ok = check_password(user.password,
request.form['password'])
except ValueError:
if user.password.startswith('$2a$12'):
# old bcrypt hash
pwd_ok = check_old_password(user.password,
request.form['password'])
if pwd_ok:
user.password = password_hash(
request.form['password'])
write_user(user)
else:
pwd_ok = False

if pwd_ok and user.is_active:
login_user(user, remember=('remember' in request.form))
return redirect(url_for('index'))
else:
alert = "Invalid credentials."
code = 401

else:
alert = 'Invalid credentials.'
code = 401
Expand Down Expand Up @@ -826,8 +858,15 @@ def acp_account():
action = 'save'
data = request.form
if data['newpwd1']:
if data['newpwd1'] == data['newpwd2'] and check_password(
current_user.password, data['oldpwd']):
try:
pwd_ok = check_password(current_user.password, data['oldpwd'])
except ValueError:
if current_user.password.startswith('$2a$12'):
# old bcrypt hash
pwd_ok = check_old_password(current_user.password,
data['oldpwd'])

if data['newpwd1'] == data['newpwd2'] and pwd_ok:
current_user.password = password_hash(data['newpwd1'])
current_user.must_change_password = False
else:
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Expand Up @@ -15,6 +15,7 @@ lxml==3.4.1
Mako==1.0.0
MarkupSafe==0.23
natsort==3.5.1
passlib==1.6.2
Pillow==2.7.0
py-bcrypt==0.4
Pygments==2.0.1
Expand Down

0 comments on commit 6075474

Please sign in to comment.