2018-05-08 14:32:07 +00:00
|
|
|
import binascii
|
|
|
|
import hashlib
|
|
|
|
|
2018-06-10 08:55:16 +00:00
|
|
|
from rest_framework import authentication, exceptions
|
2018-05-08 14:32:07 +00:00
|
|
|
|
|
|
|
from funkwhale_api.users.models import User
|
|
|
|
|
|
|
|
|
|
|
|
def get_token(salt, password):
|
|
|
|
to_hash = password + salt
|
|
|
|
h = hashlib.md5()
|
2018-06-09 13:36:16 +00:00
|
|
|
h.update(to_hash.encode("utf-8"))
|
2018-05-08 14:32:07 +00:00
|
|
|
return h.hexdigest()
|
|
|
|
|
|
|
|
|
|
|
|
def authenticate(username, password):
|
|
|
|
try:
|
2018-06-09 13:36:16 +00:00
|
|
|
if password.startswith("enc:"):
|
|
|
|
password = password.replace("enc:", "", 1)
|
|
|
|
password = binascii.unhexlify(password).decode("utf-8")
|
2018-05-08 14:32:07 +00:00
|
|
|
user = User.objects.get(
|
2018-06-28 14:47:45 +00:00
|
|
|
username__iexact=username, is_active=True, subsonic_api_token=password
|
2018-05-08 14:32:07 +00:00
|
|
|
)
|
2018-06-09 13:36:16 +00:00
|
|
|
except (User.DoesNotExist, binascii.Error):
|
|
|
|
raise exceptions.AuthenticationFailed("Wrong username or password.")
|
2018-05-08 14:32:07 +00:00
|
|
|
|
|
|
|
return (user, None)
|
|
|
|
|
|
|
|
|
|
|
|
def authenticate_salt(username, salt, token):
|
|
|
|
try:
|
|
|
|
user = User.objects.get(
|
2018-06-09 13:36:16 +00:00
|
|
|
username=username, is_active=True, subsonic_api_token__isnull=False
|
2018-05-08 14:32:07 +00:00
|
|
|
)
|
2018-06-09 13:36:16 +00:00
|
|
|
except User.DoesNotExist:
|
|
|
|
raise exceptions.AuthenticationFailed("Wrong username or password.")
|
2018-05-08 14:32:07 +00:00
|
|
|
expected = get_token(salt, user.subsonic_api_token)
|
|
|
|
if expected != token:
|
2018-06-09 13:36:16 +00:00
|
|
|
raise exceptions.AuthenticationFailed("Wrong username or password.")
|
2018-05-08 14:32:07 +00:00
|
|
|
|
|
|
|
return (user, None)
|
|
|
|
|
|
|
|
|
|
|
|
class SubsonicAuthentication(authentication.BaseAuthentication):
|
|
|
|
def authenticate(self, request):
|
|
|
|
data = request.GET or request.POST
|
2018-06-09 13:36:16 +00:00
|
|
|
username = data.get("u")
|
2018-05-08 14:32:07 +00:00
|
|
|
if not username:
|
|
|
|
return None
|
|
|
|
|
2018-06-09 13:36:16 +00:00
|
|
|
p = data.get("p")
|
|
|
|
s = data.get("s")
|
|
|
|
t = data.get("t")
|
2018-05-08 14:32:07 +00:00
|
|
|
if not p and (not s or not t):
|
2018-06-09 13:36:16 +00:00
|
|
|
raise exceptions.AuthenticationFailed("Missing credentials")
|
2018-05-08 14:32:07 +00:00
|
|
|
|
|
|
|
if p:
|
|
|
|
return authenticate(username, p)
|
|
|
|
|
|
|
|
return authenticate_salt(username, s, t)
|