big change to the webui auth system
added converting of old 1.1 config files added converting of old md5 passwords to sha1
This commit is contained in:
parent
2766c103e2
commit
af4c73a594
|
@ -27,4 +27,123 @@ AUTH_LEVEL_READONLY = 1
|
|||
AUTH_LEVEL_NORMAL = 5
|
||||
AUTH_LEVEL_ADMIN = 10
|
||||
|
||||
AUTH_LEVEL_DEFAULT = AUTH_LEVEL_NORMAL
|
||||
AUTH_LEVEL_DEFAULT = AUTH_LEVEL_NORMAL
|
||||
|
||||
import time
|
||||
import random
|
||||
import hashlib
|
||||
import logging
|
||||
|
||||
from twisted.internet.defer import Deferred
|
||||
|
||||
from deluge import component
|
||||
from deluge.ui.web.json_api import JSONComponent, export
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class Auth(JSONComponent):
|
||||
|
||||
def __init__(self):
|
||||
super(Auth, self).__init__("Auth")
|
||||
|
||||
def _create_session(self, login='admin'):
|
||||
m = hashlib.md5()
|
||||
m.update(login)
|
||||
m.update(str(time.time()))
|
||||
m.update(str(random.getrandbits(40)))
|
||||
m.update(m.hexdigest())
|
||||
session_id = m.hexdigest()
|
||||
|
||||
log.debug("Creating session for %s", login)
|
||||
config = component.get("DelugeWeb").config
|
||||
|
||||
if type(config["sessions"]) is list:
|
||||
config.config["sessions"] = {}
|
||||
|
||||
config["sessions"][session_id] = {
|
||||
"login": login
|
||||
}
|
||||
return session_id
|
||||
|
||||
@export
|
||||
def change_password(self, new_password):
|
||||
salt = hashlib.sha1(str(random.getrandbits(40))).hexdigest()
|
||||
s = hashlib.sha1(salt)
|
||||
s.update(new_password)
|
||||
config = component.get("DelugeWeb").config
|
||||
config["pwd_salt"] = salt
|
||||
config["pwd_sha1"] = s.hexdigest()
|
||||
log.debug("Changing password")
|
||||
|
||||
@export
|
||||
def check_session(self, session_id):
|
||||
d = Deferred()
|
||||
config = component.get("DelugeWeb").config
|
||||
d.callback(session_id in config["sessions"])
|
||||
return d
|
||||
|
||||
@export
|
||||
def delete_session(self, session_id):
|
||||
d = Deferred()
|
||||
config = component.get("DelugeWeb").config
|
||||
del config["sessions"][session_id]
|
||||
d.callback(True)
|
||||
return d
|
||||
|
||||
@export
|
||||
def login(self, password):
|
||||
"""Method to allow the webui to authenticate
|
||||
"""
|
||||
config = component.get("DelugeWeb").config
|
||||
d = Deferred()
|
||||
|
||||
if "old_pwd_md5" in config.config:
|
||||
# We are using the 1.1 webui auth method
|
||||
log.debug("Received a login via the 1.1 auth method")
|
||||
from base64 import decodestring
|
||||
m = hashlib.md5()
|
||||
m.update(decodestring(config["old_pwd_salt"]))
|
||||
m.update(password)
|
||||
if m.digest() == decodestring(config["old_pwd_md5"]):
|
||||
# We have a match, so we can create and return a session id.
|
||||
d.callback(self._create_session())
|
||||
|
||||
# We also want to move the password over to sha1 and remove
|
||||
# the old passwords from the config file.
|
||||
self.change_password(password)
|
||||
del config.config["old_pwd_salt"]
|
||||
del config.config["old_pwd_md5"]
|
||||
|
||||
elif "pwd_md5" in config.config:
|
||||
# We are using the 1.2-dev auth method
|
||||
log.debug("Received a login via the 1.2-dev auth method")
|
||||
m = hashlib.md5()
|
||||
m.update(config["pwd_salt"])
|
||||
m.update(password)
|
||||
if m.hexdigest() == config['pwd_md5']:
|
||||
# We have a match, so we can create and return a session id.
|
||||
d.callback(self._create_session())
|
||||
|
||||
# We also want to move the password over to sha1 and remove
|
||||
# the old passwords from the config file.
|
||||
self.change_password(password)
|
||||
del config.config["pwd_md5"]
|
||||
del config.config["pwd_salt"]
|
||||
|
||||
elif "pwd_sha1" in config.config:
|
||||
# We are using the 1.2 auth method
|
||||
log.debug("Received a login via the 1.2 auth method")
|
||||
s = hashlib.sha1()
|
||||
s.update(config["pwd_salt"])
|
||||
s.update(password)
|
||||
if s.hexdigest() == config["pwd_sha1"]:
|
||||
# We have a match, so we can create and return a session id.
|
||||
d.callback(self._create_session())
|
||||
|
||||
else:
|
||||
# Can't detect which method we should be using so just deny
|
||||
# access.
|
||||
log.debug("Failed to detect the login method")
|
||||
d.callback(False)
|
||||
|
||||
return d
|
|
@ -84,7 +84,7 @@ Copyright:
|
|||
|
||||
onLogin: function() {
|
||||
var passwordField = this.loginForm.items.get('password');
|
||||
Deluge.Client.web.login(passwordField.getValue(), {
|
||||
Deluge.Client.auth.login(passwordField.getValue(), {
|
||||
success: function(result) {
|
||||
if (result) {
|
||||
Deluge.Events.fire('login');
|
||||
|
@ -112,7 +112,7 @@ Copyright:
|
|||
onLogout: function() {
|
||||
var session = Deluge.UI.cookies.get("session", false);
|
||||
if (session) {
|
||||
Deluge.Client.web.delete_session(session, {
|
||||
Deluge.Client.auth.delete_session(session, {
|
||||
success: function(result) {
|
||||
Deluge.UI.cookies.clear("session");
|
||||
this.show();
|
||||
|
@ -125,7 +125,7 @@ Copyright:
|
|||
onBeforeShow: function() {
|
||||
var session = Deluge.UI.cookies.get("session", false);
|
||||
if (session) {
|
||||
Deluge.Client.web.check_session(session, {
|
||||
Deluge.Client.auth.check_session(session, {
|
||||
success: function(result) {
|
||||
if (result) {
|
||||
Deluge.Events.fire('login');
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -25,10 +25,9 @@
|
|||
import os
|
||||
import time
|
||||
import base64
|
||||
import random
|
||||
import urllib
|
||||
import hashlib
|
||||
import logging
|
||||
import hashlib
|
||||
import tempfile
|
||||
|
||||
from types import FunctionType
|
||||
|
@ -39,12 +38,20 @@ from deluge import common, component
|
|||
from deluge.configmanager import ConfigManager
|
||||
from deluge.ui import common as uicommon
|
||||
from deluge.ui.client import client, Client
|
||||
from deluge.ui.web.auth import *
|
||||
|
||||
from deluge.ui.web.common import _
|
||||
json = common.json
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
AUTH_LEVEL_DEFAULT = None
|
||||
|
||||
class JSONComponent(component.Component):
|
||||
def __init__(self, name, interval=1, depend=None):
|
||||
super(JSONComponent, self).__init__(name, interval, depend)
|
||||
self._json = component.get("JSON")
|
||||
self._json.register_object(self, name)
|
||||
|
||||
def export(auth_level=AUTH_LEVEL_DEFAULT):
|
||||
"""
|
||||
Decorator function to register an object's method as an RPC. The object
|
||||
|
@ -54,6 +61,10 @@ def export(auth_level=AUTH_LEVEL_DEFAULT):
|
|||
:param auth_level: int, the auth level required to call this method
|
||||
|
||||
"""
|
||||
global AUTH_LEVEL_DEFAULT
|
||||
if AUTH_LEVEL_DEFAULT is None:
|
||||
from deluge.ui.web.auth import AUTH_LEVEL_DEFAULT
|
||||
|
||||
def wrap(func, *args, **kwargs):
|
||||
func._json_export = True
|
||||
func._json_auth_level = auth_level
|
||||
|
@ -245,13 +256,6 @@ class JSON(resource.Resource, component.Component):
|
|||
log.debug("Registering method: %s", name + "." + d)
|
||||
self._local_methods[name + "." + d] = getattr(obj, d)
|
||||
|
||||
class JSONComponent(component.Component):
|
||||
def __init__(self, name, interval=1, depend=None):
|
||||
super(JSONComponent, self).__init__(name, interval, depend)
|
||||
self._json = component.get("JSON")
|
||||
self._json.register_object(self, name)
|
||||
|
||||
|
||||
DEFAULT_HOST = "127.0.0.1"
|
||||
DEFAULT_PORT = 58846
|
||||
|
||||
|
@ -435,51 +439,6 @@ class WebApi(JSONComponent):
|
|||
d.callback(True)
|
||||
return d
|
||||
|
||||
def _create_session(self, login='admin'):
|
||||
m = hashlib.md5()
|
||||
m.update(login)
|
||||
m.update(str(time.time()))
|
||||
m.update(str(random.getrandbits(999)))
|
||||
m.update(m.hexdigest())
|
||||
session_id = m.hexdigest()
|
||||
|
||||
config = component.get("DelugeWeb").config
|
||||
config["sessions"][session_id] = {
|
||||
"login": login
|
||||
}
|
||||
return session_id
|
||||
|
||||
@export
|
||||
def check_session(self, session_id):
|
||||
d = Deferred()
|
||||
config = component.get("DelugeWeb").config
|
||||
d.callback(session_id in config["sessions"])
|
||||
return d
|
||||
|
||||
@export
|
||||
def delete_session(self, session_id):
|
||||
d = Deferred()
|
||||
config = component.get("DelugeWeb").config
|
||||
del config["sessions"][session_id]
|
||||
d.callback(True)
|
||||
return d
|
||||
|
||||
@export
|
||||
def login(self, password):
|
||||
"""Method to allow the webui to authenticate
|
||||
"""
|
||||
config = component.get("DelugeWeb").config
|
||||
m = hashlib.md5()
|
||||
m.update(config['pwd_salt'])
|
||||
m.update(password)
|
||||
d = Deferred()
|
||||
if m.hexdigest() == config['pwd_md5']:
|
||||
# Change this to return a session id
|
||||
d.callback(self._create_session())
|
||||
else:
|
||||
d.callback(False)
|
||||
return d
|
||||
|
||||
@export
|
||||
def get_hosts(self):
|
||||
"""Return the hosts in the hostlist"""
|
||||
|
|
|
@ -43,6 +43,7 @@ from deluge.configmanager import ConfigManager
|
|||
from deluge.log import setupLogger, LOG as _log
|
||||
from deluge.ui import common as uicommon
|
||||
from deluge.ui.tracker_icons import TrackerIcons
|
||||
from deluge.ui.web.auth import Auth
|
||||
from deluge.ui.web.common import Template
|
||||
from deluge.ui.web.json_api import JSON, WebApi
|
||||
from deluge.ui.web.pluginmanager import PluginManager
|
||||
|
@ -69,17 +70,24 @@ CONFIG_DEFAULTS = {
|
|||
"port": 8112,
|
||||
"enabled_plugins": [],
|
||||
"theme": "slate",
|
||||
"pwd_salt": "16f65d5c79b7e93278a28b60fed2431e",
|
||||
"pwd_md5": "2c9baa929ca38fb5c9eb5b054474d1ce",
|
||||
"pwd_salt": "c26ab3bbd8b137f99cd83c2c1c0963bcc1a35cad",
|
||||
"pwd_sha1": "2ce1a410bcdcc53064129b6d950f2e9fee4edc1e",
|
||||
"base": "",
|
||||
"sessions": {},
|
||||
"sidebar_show_zero": False,
|
||||
"sidebar_show_trackers": False,
|
||||
"show_keyword_search": False,
|
||||
"show_sidebar": True,
|
||||
"cache_templates": False,
|
||||
"https": False
|
||||
}
|
||||
|
||||
OLD_CONFIG_KEYS = (
|
||||
"port", "enabled_plugins", "base", "sidebar_show_zero",
|
||||
"sidebar_show_trackers", "show_keyword_search", "show_sidebar",
|
||||
"cache_templates", "https"
|
||||
)
|
||||
|
||||
def rpath(path):
|
||||
"""Convert a relative path into an absolute path relative to the location
|
||||
of this script.
|
||||
|
@ -340,11 +348,34 @@ class DelugeWeb(component.Component):
|
|||
def __init__(self):
|
||||
super(DelugeWeb, self).__init__("DelugeWeb")
|
||||
self.config = ConfigManager("web.conf", CONFIG_DEFAULTS)
|
||||
|
||||
old_config = ConfigManager("webui06.conf")
|
||||
if old_config.config:
|
||||
# we have an old config file here to handle so we should move
|
||||
# all the values across to the new config file, and then remove
|
||||
# it.
|
||||
for key in OLD_CONFIG_KEYS:
|
||||
self.config[key] = old_config[key]
|
||||
|
||||
# We need to base64 encode the passwords since utf-8 can't handle
|
||||
# them otherwise.
|
||||
from base64 import encodestring
|
||||
self.config["old_pwd_md5"] = encodestring(old_config["pwd_md5"])
|
||||
self.config["old_pwd_salt"] = encodestring(old_config["pwd_salt"])
|
||||
|
||||
# Save our config and if it saved successfully then rename the
|
||||
# old configuration file.
|
||||
if self.config.save():
|
||||
config_dir = os.path.dirname(old_config.config_file)
|
||||
backup_path = os.path.join(config_dir, 'web.conf.old')
|
||||
os.rename(old_config.config_file, backup_path)
|
||||
del old_config
|
||||
|
||||
self.top_level = TopLevel()
|
||||
self.site = server.Site(self.top_level)
|
||||
self.port = self.config["port"]
|
||||
self.web_api = WebApi()
|
||||
self.auth = Auth()
|
||||
|
||||
# Since twisted assigns itself all the signals may as well make
|
||||
# use of it.
|
||||
|
|
Loading…
Reference in New Issue