2016-11-20 01:29:39 +01:00
|
|
|
"""
|
2016-11-20 02:00:18 +01:00
|
|
|
login.py - Implement core login abstraction.
|
2016-11-20 01:29:39 +01:00
|
|
|
"""
|
|
|
|
|
|
|
|
from pylinkirc import conf, utils, world
|
|
|
|
from pylinkirc.log import log
|
2016-12-10 02:15:53 +01:00
|
|
|
|
|
|
|
try:
|
|
|
|
from passlib.context import CryptContext
|
|
|
|
except ImportError:
|
2017-01-23 01:16:25 +01:00
|
|
|
CryptContext = None
|
|
|
|
log.warning("Hashed passwords are disabled because passlib is not installed. Please install "
|
|
|
|
"it (pip3 install passlib) and restart for this feature to work.")
|
2016-11-20 02:47:55 +01:00
|
|
|
|
2017-01-23 01:16:25 +01:00
|
|
|
pwd_context = None
|
|
|
|
if CryptContext:
|
|
|
|
pwd_context = CryptContext(["sha512_crypt", "sha256_crypt"],
|
|
|
|
all__vary_rounds=0.1,
|
|
|
|
sha256_crypt__default_rounds=180000,
|
|
|
|
sha512_crypt__default_rounds=90000)
|
2016-11-20 01:29:39 +01:00
|
|
|
|
2016-11-20 01:29:53 +01:00
|
|
|
def checkLogin(user, password):
|
|
|
|
"""Checks whether the given user and password is a valid combination."""
|
2016-11-20 02:00:18 +01:00
|
|
|
accounts = conf.conf['login'].get('accounts')
|
|
|
|
if not accounts:
|
|
|
|
# No accounts specified, return.
|
|
|
|
return False
|
|
|
|
|
|
|
|
# Lowercase account names to make them case insensitive. TODO: check for
|
|
|
|
# duplicates.
|
|
|
|
user = user.lower()
|
|
|
|
accounts = {k.lower(): v for k, v in accounts.items()}
|
|
|
|
|
2016-11-20 01:29:39 +01:00
|
|
|
try:
|
2016-11-20 02:00:18 +01:00
|
|
|
account = accounts[user]
|
2016-11-20 01:29:53 +01:00
|
|
|
except KeyError: # Invalid combination
|
2016-11-20 01:29:39 +01:00
|
|
|
return False
|
2016-11-20 02:00:18 +01:00
|
|
|
else:
|
|
|
|
passhash = account.get('password')
|
|
|
|
if not passhash:
|
|
|
|
# No password given, return. XXX: we should allow plugins to override
|
|
|
|
# this in the future.
|
|
|
|
return False
|
2016-11-20 01:29:39 +01:00
|
|
|
|
2016-11-20 02:00:18 +01:00
|
|
|
# Encryption in account passwords is optional (to not break backwards
|
|
|
|
# compatibility).
|
|
|
|
if account.get('encrypted', False):
|
|
|
|
return verifyHash(password, passhash)
|
|
|
|
else:
|
|
|
|
return password == passhash
|
2016-11-20 01:29:53 +01:00
|
|
|
|
|
|
|
def verifyHash(password, passhash):
|
|
|
|
"""Checks whether the password given matches the hash."""
|
|
|
|
if password:
|
2017-01-23 01:16:25 +01:00
|
|
|
if not pwd_context:
|
|
|
|
raise utils.NotAuthorizedError("Cannot log in to an account with a hashed password "
|
|
|
|
"because passlib is not installed.")
|
2016-11-20 01:29:53 +01:00
|
|
|
|
2017-01-23 01:16:25 +01:00
|
|
|
return pwd_context.verify(password, passhash)
|
|
|
|
return False # No password given!
|