mirror of
https://github.com/jlu5/PyLink.git
synced 2024-11-01 01:09:22 +01:00
Switch 'identify' to use the new login backend, add passlib to README dependencies
This new backend supports optional encryption (sha256_crypt / sha512_crypt via passlib). Closes #322.
This commit is contained in:
parent
69066029f1
commit
b1e4b34b79
@ -41,6 +41,7 @@ First, make sure the following dependencies are met:
|
|||||||
* Setuptools (`pip3 install setuptools`)
|
* Setuptools (`pip3 install setuptools`)
|
||||||
* PyYAML (`pip3 install pyyaml`)
|
* PyYAML (`pip3 install pyyaml`)
|
||||||
* [ircmatch](https://github.com/mammon-ircd/ircmatch) (`pip3 install ircmatch`)
|
* [ircmatch](https://github.com/mammon-ircd/ircmatch) (`pip3 install ircmatch`)
|
||||||
|
* passlib (`pip3 install passlib`)
|
||||||
* *For the servprotect plugin*: [expiringdict](https://github.com/mailgun/expiringdict) (install this from source; installation is broken in pip due to [mailgun/expiringdict#13](https://github.com/mailgun/expiringdict/issues/13))
|
* *For the servprotect plugin*: [expiringdict](https://github.com/mailgun/expiringdict) (install this from source; installation is broken in pip due to [mailgun/expiringdict#13](https://github.com/mailgun/expiringdict/issues/13))
|
||||||
|
|
||||||
1) Clone the repository: `git clone https://github.com/GLolol/PyLink && cd PyLink`
|
1) Clone the repository: `git clone https://github.com/GLolol/PyLink && cd PyLink`
|
||||||
|
@ -9,7 +9,7 @@ import gc
|
|||||||
import sys
|
import sys
|
||||||
import importlib
|
import importlib
|
||||||
|
|
||||||
from . import control
|
from . import control, login
|
||||||
from pylinkirc import utils, world, conf
|
from pylinkirc import utils, world, conf
|
||||||
from pylinkirc.log import log
|
from pylinkirc.log import log
|
||||||
|
|
||||||
@ -43,27 +43,18 @@ def identify(irc, source, args):
|
|||||||
irc.reply('Error: Not enough arguments.')
|
irc.reply('Error: Not enough arguments.')
|
||||||
return
|
return
|
||||||
|
|
||||||
username = username.lower()
|
# Process new-style accounts.
|
||||||
|
if login.checkLogin(username, password):
|
||||||
|
_login(irc, source, username)
|
||||||
|
return
|
||||||
|
|
||||||
# Process new-style accounts. Note: usernames are case-insensitive, passwords are NOT.
|
# Process legacy logins (login:user).
|
||||||
for account, block in conf.conf['login'].get('accounts', {}).items():
|
if username.lower() == conf.conf['login'].get('user', '').lower() and password == conf.conf['login'].get('password'):
|
||||||
if account.lower() == username:
|
realuser = conf.conf['login']['user']
|
||||||
# Username matched config.
|
_login(irc, source, realuser)
|
||||||
if password and password == block.get('password'):
|
|
||||||
# Password exists and matched config. TODO: hash user passwords in config.
|
|
||||||
_login(irc, source, account)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
_loginfail(irc, source, account)
|
|
||||||
break
|
|
||||||
else:
|
else:
|
||||||
# Process legacy logins (login:user).
|
# Username not found.
|
||||||
if username.lower() == conf.conf['login'].get('user', '').lower() and password == conf.conf['login'].get('password'):
|
_loginfail(irc, source, username)
|
||||||
realuser = conf.conf['login']['user']
|
|
||||||
_login(irc, source, realuser)
|
|
||||||
else:
|
|
||||||
# Username not found.
|
|
||||||
_loginfail(irc, source, username)
|
|
||||||
|
|
||||||
|
|
||||||
@utils.add_cmd
|
@utils.add_cmd
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
login.py - Implement core login abstraction
|
login.py - Implement core login abstraction.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from pylinkirc import conf, utils, world
|
from pylinkirc import conf, utils, world
|
||||||
@ -8,12 +8,33 @@ from passlib.apps import custom_app_context as pwd_context
|
|||||||
|
|
||||||
def checkLogin(user, password):
|
def checkLogin(user, password):
|
||||||
"""Checks whether the given user and password is a valid combination."""
|
"""Checks whether the given user and password is a valid combination."""
|
||||||
try:
|
accounts = conf.conf['login'].get('accounts')
|
||||||
passhash = conf.conf['login']['accounts'][user].get('password')
|
if not accounts:
|
||||||
except KeyError: # Invalid combination
|
# No accounts specified, return.
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return verifyHash(password, passhash)
|
# 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()}
|
||||||
|
|
||||||
|
try:
|
||||||
|
account = accounts[user]
|
||||||
|
except KeyError: # Invalid combination
|
||||||
|
return False
|
||||||
|
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
|
||||||
|
|
||||||
|
# Encryption in account passwords is optional (to not break backwards
|
||||||
|
# compatibility).
|
||||||
|
if account.get('encrypted', False):
|
||||||
|
return verifyHash(password, passhash)
|
||||||
|
else:
|
||||||
|
return password == passhash
|
||||||
|
|
||||||
def verifyHash(password, passhash):
|
def verifyHash(password, passhash):
|
||||||
"""Checks whether the password given matches the hash."""
|
"""Checks whether the password given matches the hash."""
|
||||||
@ -38,6 +59,7 @@ def mkpasswd(irc, source, args):
|
|||||||
return
|
return
|
||||||
if not password:
|
if not password:
|
||||||
irc.error("Password cannot be empty.")
|
irc.error("Password cannot be empty.")
|
||||||
|
return
|
||||||
|
|
||||||
hashed_pass = pwd_context.encrypt(password)
|
hashed_pass = pwd_context.encrypt(password)
|
||||||
irc.reply(hashed_pass, private=True)
|
irc.reply(hashed_pass, private=True)
|
||||||
|
Loading…
Reference in New Issue
Block a user