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:
Damien Churchill 2009-05-07 16:27:22 +00:00
parent 2766c103e2
commit af4c73a594
5 changed files with 171 additions and 62 deletions

View File

@ -28,3 +28,122 @@ AUTH_LEVEL_NORMAL = 5
AUTH_LEVEL_ADMIN = 10
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

View File

@ -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

View File

@ -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"""

View File

@ -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.
@ -341,10 +349,33 @@ class DelugeWeb(component.Component):
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.