|
1 | 1 | # -*- coding: utf-8 -*-
|
2 | 2 |
|
3 |
| -# Coil CMS v1.0.0 |
| 3 | +# Coil CMS v1.1.0 |
4 | 4 | # Copyright © 2014-2015 Chris Warrick, Roberto Alsina, Henry Hirsch et al.
|
5 | 5 |
|
6 | 6 | # Permission is hereby granted, free of charge, to any
|
|
43 | 43 | url_for)
|
44 | 44 | from flask.ext.login import (LoginManager, login_required, login_user,
|
45 | 45 | logout_user, current_user, make_secure_token)
|
46 |
| -from flask.ext.bcrypt import Bcrypt |
| 46 | +from passlib.hash import bcrypt_sha256 |
47 | 47 | from coil.utils import USER_FIELDS, PERMISSIONS, PERMISSIONS_E, SiteProxy
|
48 | 48 | from coil.forms import (LoginForm, NewPostForm, NewPageForm, DeleteForm,
|
49 | 49 | UserDeleteForm, UserEditForm, AccountForm,
|
@@ -78,7 +78,6 @@ def configure_site():
|
78 | 78 | _dn = nikola.__main__.main([])
|
79 | 79 | _dn.sub_cmds = _dn.get_commands()
|
80 | 80 | _site = _dn.nikola
|
81 |
| - app.config['BCRYPT_LOG_ROUNDS'] = 12 |
82 | 81 | app.config['NIKOLA_ROOT'] = os.getcwd()
|
83 | 82 | app.config['DEBUG'] = False
|
84 | 83 |
|
@@ -183,26 +182,45 @@ def configure_site():
|
183 | 182 |
|
184 | 183 |
|
185 | 184 | def password_hash(password):
|
186 |
| - """Hash the password, using bcrypt. |
| 185 | + """Hash the password, using bcrypt+sha256. |
| 186 | +
|
| 187 | + .. versionchanged:: 1.1.0 |
187 | 188 |
|
188 | 189 | :param str password: Password in plaintext
|
189 | 190 | :return: password hash
|
190 | 191 | :rtype: str
|
191 | 192 | """
|
192 |
| - return bcrypt.generate_password_hash(password) |
| 193 | + return bcrypt_sha256.encrypt(password) |
193 | 194 |
|
194 | 195 |
|
195 | 196 | def check_password(pwdhash, password):
|
196 | 197 | """Check the password hash from :func:`password_hash`.
|
197 | 198 |
|
| 199 | + .. versionchanged:: 1.1.0 |
| 200 | +
|
198 | 201 | :param str pwdhash: Hash from :func:`password_hash` to check
|
199 | 202 | :param str password: Password in plaintext
|
200 | 203 | :return: password match
|
201 | 204 | :rtype: bool
|
202 | 205 | """
|
203 |
| - return bcrypt.check_password_hash(pwdhash, password) |
| 206 | + return bcrypt_sha256.verify(password, pwdhash) |
204 | 207 |
|
205 | 208 |
|
| 209 | +def check_old_password(pwdhash, password): |
| 210 | + """Check the old password hash from :func:`password_hash`. |
| 211 | +
|
| 212 | + .. versionadded:: 1.1.0 |
| 213 | +
|
| 214 | + :param str pwdhash: Hash from :func:`password_hash` to check |
| 215 | + :param str password: Password in plaintext |
| 216 | + :return: password match |
| 217 | + :rtype: bool |
| 218 | + """ |
| 219 | + from flask.ext.bcrypt import Bcrypt |
| 220 | + app.config['BCRYPT_LOG_ROUNDS'] = 12 |
| 221 | + bcrypt = Bcrypt(app) |
| 222 | + return bcrypt.check_password_hash(pwdhash, password) |
| 223 | + |
206 | 224 | def generate_menu():
|
207 | 225 | """Generate ``menu`` with the rebuild link.
|
208 | 226 |
|
@@ -355,7 +373,6 @@ def log_request(resp):
|
355 | 373 | app.http_logger.error(l)
|
356 | 374 | return resp
|
357 | 375 |
|
358 |
| -bcrypt = Bcrypt(app) |
359 | 376 | login_manager = LoginManager()
|
360 | 377 | login_manager.init_app(app)
|
361 | 378 | login_manager.unauthorized_callback = _unauthorized
|
@@ -476,13 +493,28 @@ def login():
|
476 | 493 | alert = 'Invalid credentials.'
|
477 | 494 | code = 401
|
478 | 495 | else:
|
479 |
| - if check_password(user.password, |
480 |
| - request.form['password']) and user.is_active: |
| 496 | + try: |
| 497 | + pwd_ok = check_password(user.password, |
| 498 | + request.form['password']) |
| 499 | + except ValueError: |
| 500 | + if user.password.startswith('$2a$12'): |
| 501 | + # old bcrypt hash |
| 502 | + pwd_ok = check_old_password(user.password, |
| 503 | + request.form['password']) |
| 504 | + if pwd_ok: |
| 505 | + user.password = password_hash( |
| 506 | + request.form['password']) |
| 507 | + write_user(user) |
| 508 | + else: |
| 509 | + pwd_ok = False |
| 510 | + |
| 511 | + if pwd_ok and user.is_active: |
481 | 512 | login_user(user, remember=('remember' in request.form))
|
482 | 513 | return redirect(url_for('index'))
|
483 | 514 | else:
|
484 | 515 | alert = "Invalid credentials."
|
485 | 516 | code = 401
|
| 517 | + |
486 | 518 | else:
|
487 | 519 | alert = 'Invalid credentials.'
|
488 | 520 | code = 401
|
@@ -826,8 +858,15 @@ def acp_account():
|
826 | 858 | action = 'save'
|
827 | 859 | data = request.form
|
828 | 860 | if data['newpwd1']:
|
829 |
| - if data['newpwd1'] == data['newpwd2'] and check_password( |
830 |
| - current_user.password, data['oldpwd']): |
| 861 | + try: |
| 862 | + pwd_ok = check_password(current_user.password, data['oldpwd']) |
| 863 | + except ValueError: |
| 864 | + if current_user.password.startswith('$2a$12'): |
| 865 | + # old bcrypt hash |
| 866 | + pwd_ok = check_old_password(current_user.password, |
| 867 | + data['oldpwd']) |
| 868 | + |
| 869 | + if data['newpwd1'] == data['newpwd2'] and pwd_ok: |
831 | 870 | current_user.password = password_hash(data['newpwd1'])
|
832 | 871 | current_user.must_change_password = False
|
833 | 872 | else:
|
|
0 commit comments