Force backwards incompatibility.
Force clients prior to 1.4 to fail authentication, this was we might reduce tickets like #1852.
This commit is contained in:
parent
552c898998
commit
0ba0e013b5
|
@ -56,7 +56,8 @@ except ImportError:
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
import deluge.configmanager
|
import deluge.configmanager
|
||||||
from deluge.core.authmanager import AUTH_LEVEL_NONE, AUTH_LEVEL_DEFAULT, AUTH_LEVEL_ADMIN
|
from deluge.core.authmanager import AUTH_LEVEL_NONE, AUTH_LEVEL_DEFAULT, AUTH_LEVEL_ADMIN
|
||||||
from deluge.error import DelugeError, NotAuthorizedError, _PassthroughError
|
from deluge.error import (DelugeError, NotAuthorizedError, _PassthroughError,
|
||||||
|
IncompatibleClient)
|
||||||
|
|
||||||
RPC_RESPONSE = 1
|
RPC_RESPONSE = 1
|
||||||
RPC_ERROR = 2
|
RPC_ERROR = 2
|
||||||
|
@ -261,6 +262,13 @@ class DelugeRPCProtocol(Protocol):
|
||||||
# We need to authenticate the user here
|
# We need to authenticate the user here
|
||||||
log.debug("RPC dispatch daemon.login")
|
log.debug("RPC dispatch daemon.login")
|
||||||
try:
|
try:
|
||||||
|
client_version = kwargs.pop('client_version', None)
|
||||||
|
if client_version is None:
|
||||||
|
raise IncompatibleClient(
|
||||||
|
"Your deluge client is not compatible with the daemon. "
|
||||||
|
"Please upgrade your client to %s" %
|
||||||
|
deluge.common.get_version()
|
||||||
|
)
|
||||||
ret = component.get("AuthManager").authorize(*args, **kwargs)
|
ret = component.get("AuthManager").authorize(*args, **kwargs)
|
||||||
if ret:
|
if ret:
|
||||||
self.factory.authorized_sessions[self.transport.sessionno] = (ret, args[0])
|
self.factory.authorized_sessions[self.transport.sessionno] = (ret, args[0])
|
||||||
|
|
|
@ -65,6 +65,9 @@ class _PassthroughError(DelugeError):
|
||||||
inst._kwargs = kwargs
|
inst._kwargs = kwargs
|
||||||
return inst
|
return inst
|
||||||
|
|
||||||
|
class IncompatibleClient(_PassthroughError):
|
||||||
|
pass
|
||||||
|
|
||||||
class NotAuthorizedError(_PassthroughError):
|
class NotAuthorizedError(_PassthroughError):
|
||||||
|
|
||||||
def __init__(self, current_level, required_level):
|
def __init__(self, current_level, required_level):
|
||||||
|
|
|
@ -1,11 +1,65 @@
|
||||||
|
|
||||||
import common
|
import common
|
||||||
|
|
||||||
|
from twisted.internet import defer
|
||||||
from twisted.trial import unittest
|
from twisted.trial import unittest
|
||||||
|
|
||||||
from deluge import error
|
from deluge import error
|
||||||
from deluge.core.authmanager import AUTH_LEVEL_ADMIN, AUTH_LEVEL_DEFAULT
|
from deluge.core.authmanager import AUTH_LEVEL_ADMIN
|
||||||
from deluge.ui.client import client
|
from deluge.ui.client import client, Client, DaemonSSLProxy
|
||||||
|
|
||||||
|
|
||||||
|
class NoVersionSendingDaemonSSLProxy(DaemonSSLProxy):
|
||||||
|
def authenticate(self, username, password):
|
||||||
|
self.login_deferred = defer.Deferred()
|
||||||
|
d = self.call("daemon.login", username, password)
|
||||||
|
d.addCallback(self.__on_login, username)
|
||||||
|
d.addErrback(self.__on_login_fail)
|
||||||
|
return self.login_deferred
|
||||||
|
|
||||||
|
def __on_login(self, result, username):
|
||||||
|
self.login_deferred.callback(result)
|
||||||
|
|
||||||
|
def __on_login_fail(self, result):
|
||||||
|
self.login_deferred.errback(result)
|
||||||
|
|
||||||
|
class NoVersionSendingClient(Client):
|
||||||
|
|
||||||
|
def connect(self, host="127.0.0.1", port=58846, username="", password="",
|
||||||
|
skip_authentication=False):
|
||||||
|
self._daemon_proxy = NoVersionSendingDaemonSSLProxy()
|
||||||
|
self._daemon_proxy.set_disconnect_callback(self.__on_disconnect)
|
||||||
|
|
||||||
|
d = self._daemon_proxy.connect(host, port)
|
||||||
|
|
||||||
|
def on_connect_fail(reason):
|
||||||
|
self.disconnect()
|
||||||
|
return reason
|
||||||
|
|
||||||
|
def on_authenticate(result, daemon_info):
|
||||||
|
return result
|
||||||
|
|
||||||
|
def on_authenticate_fail(reason):
|
||||||
|
return reason
|
||||||
|
|
||||||
|
def on_connected(daemon_version):
|
||||||
|
return daemon_version
|
||||||
|
|
||||||
|
def authenticate(daemon_version, username, password):
|
||||||
|
d = self._daemon_proxy.authenticate(username, password)
|
||||||
|
d.addCallback(on_authenticate, daemon_version)
|
||||||
|
d.addErrback(on_authenticate_fail)
|
||||||
|
return d
|
||||||
|
|
||||||
|
d.addCallback(on_connected)
|
||||||
|
d.addErrback(on_connect_fail)
|
||||||
|
if not skip_authentication:
|
||||||
|
d.addCallback(authenticate, username, password)
|
||||||
|
return d
|
||||||
|
|
||||||
|
def __on_disconnect(self):
|
||||||
|
if self.disconnect_callback:
|
||||||
|
self.disconnect_callback()
|
||||||
|
|
||||||
class ClientTestCase(unittest.TestCase):
|
class ClientTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
@ -78,3 +132,21 @@ class ClientTestCase(unittest.TestCase):
|
||||||
|
|
||||||
d.addErrback(on_failure)
|
d.addErrback(on_failure)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
def test_connect_without_sending_client_version_fails(self):
|
||||||
|
from deluge.ui import common
|
||||||
|
username, password = common.get_localhost_auth()
|
||||||
|
no_version_sending_client = NoVersionSendingClient()
|
||||||
|
d = no_version_sending_client.connect(
|
||||||
|
"localhost", 58846, username=username, password=password
|
||||||
|
)
|
||||||
|
|
||||||
|
def on_failure(failure):
|
||||||
|
self.assertEqual(
|
||||||
|
failure.trap(error.IncompatibleClient),
|
||||||
|
error.IncompatibleClient
|
||||||
|
)
|
||||||
|
self.addCleanup(no_version_sending_client.disconnect)
|
||||||
|
|
||||||
|
d.addErrback(on_failure)
|
||||||
|
return d
|
||||||
|
|
|
@ -46,7 +46,6 @@ import zlib
|
||||||
|
|
||||||
import deluge.common
|
import deluge.common
|
||||||
from deluge import error
|
from deluge import error
|
||||||
from deluge.log import LOG as log
|
|
||||||
from deluge.event import known_events
|
from deluge.event import known_events
|
||||||
|
|
||||||
if deluge.common.windows_check():
|
if deluge.common.windows_check():
|
||||||
|
@ -299,8 +298,6 @@ class DaemonSSLProxy(DaemonProxy):
|
||||||
|
|
||||||
:param host: str, the host to connect to
|
:param host: str, the host to connect to
|
||||||
:param port: int, the listening port on the daemon
|
:param port: int, the listening port on the daemon
|
||||||
:param username: str, the username to login as
|
|
||||||
:param password: str, the password to login with
|
|
||||||
|
|
||||||
:returns: twisted.Deferred
|
:returns: twisted.Deferred
|
||||||
|
|
||||||
|
@ -451,7 +448,8 @@ class DaemonSSLProxy(DaemonProxy):
|
||||||
def authenticate(self, username, password):
|
def authenticate(self, username, password):
|
||||||
log.debug("%s.authenticate: %s", self.__class__.__name__, username)
|
log.debug("%s.authenticate: %s", self.__class__.__name__, username)
|
||||||
self.login_deferred = defer.Deferred()
|
self.login_deferred = defer.Deferred()
|
||||||
d = self.call("daemon.login", username, password)
|
d = self.call("daemon.login", username, password,
|
||||||
|
client_version=deluge.common.get_version())
|
||||||
d.addCallback(self.__on_login, username)
|
d.addCallback(self.__on_login, username)
|
||||||
d.addErrback(self.__on_login_fail)
|
d.addErrback(self.__on_login_fail)
|
||||||
return self.login_deferred
|
return self.login_deferred
|
||||||
|
|
Loading…
Reference in New Issue