import re import sys import json from Config import config from Plugin import PluginManager from Crypt import CryptBitcoin import UserPlugin try: local_master_addresses = set(json.load(open("%s/users.json" % config.data_dir)).keys()) # Users in users.json except Exception, err: local_master_addresses = set() @PluginManager.registerTo("UiRequest") class UiRequestPlugin(object): def __init__(self, *args, **kwargs): self.user_manager = sys.modules["User.UserManager"].user_manager super(UiRequestPlugin, self).__init__(*args, **kwargs) # Create new user and inject user welcome message if necessary # Return: Html body also containing the injection def actionWrapper(self, path, extra_headers=None): match = re.match("/(?P
[A-Za-z0-9\._-]+)(?P/.*|$)", path) if not match: return False inner_path = match.group("inner_path").lstrip("/") html_request = "." not in inner_path or inner_path.endswith(".html") # Only inject html to html requests user_created = False if html_request: user = self.getCurrentUser() # Get user from cookie if not user: # No user found by cookie user = self.user_manager.create() user_created = True else: user = None # Disable new site creation if --multiuser_no_new_sites enabled if config.multiuser_no_new_sites: path_parts = self.parsePath(path) if not self.server.site_manager.get(match.group("address")) and (not user or user.master_address not in local_master_addresses): self.sendHeader(404) return self.formatError("Not Found", "Adding new sites disabled on this proxy", details=False) if user_created: if not extra_headers: extra_headers = {} extra_headers['Set-Cookie'] = "master_address=%s;path=/;max-age=2592000;" % user.master_address # = 30 days loggedin = self.get.get("login") == "done" back_generator = super(UiRequestPlugin, self).actionWrapper(path, extra_headers) # Get the wrapper frame output if not back_generator: # Wrapper error or not string returned, injection not possible return False elif loggedin: back = back_generator.next() inject_html = """ """.replace("\t", "") if user.master_address in local_master_addresses: message = "Hello master!" else: message = "Hello again!" inject_html = inject_html.replace("{message}", message) return iter([re.sub("\s*\s*$", inject_html, back)]) # Replace the tags with the injection else: # No injection necessary return back_generator # Get the current user based on request's cookies # Return: User object or None if no match def getCurrentUser(self): cookies = self.getCookies() user = None if "master_address" in cookies: users = self.user_manager.list() user = users.get(cookies["master_address"]) return user @PluginManager.registerTo("UiWebsocket") class UiWebsocketPlugin(object): def __init__(self, *args, **kwargs): self.multiuser_denied_cmds = ( "siteDelete", "configSet", "serverShutdown", "serverUpdate", "siteClone", "siteSetOwned", "siteSetAutodownloadoptional", "dbReload", "dbRebuild", "mergerSiteDelete", "siteSetLimit", "siteSetAutodownloadBigfileLimit", "optionalLimitSet", "optionalHelp", "optionalHelpRemove", "optionalHelpAll", "optionalFilePin", "optionalFileUnpin", "optionalFileDelete", "muteAdd", "muteRemove", "blacklistAdd", "blacklistRemove" ) if config.multiuser_no_new_sites: self.multiuser_denied_cmds += ("mergerSiteAdd", ) super(UiWebsocketPlugin, self).__init__(*args, **kwargs) # Let the page know we running in multiuser mode def formatServerInfo(self): server_info = super(UiWebsocketPlugin, self).formatServerInfo() server_info["multiuser"] = True if "ADMIN" in self.site.settings["permissions"]: server_info["master_address"] = self.user.master_address return server_info # Show current user's master seed def actionUserShowMasterSeed(self, to): if "ADMIN" not in self.site.settings["permissions"]: return self.response(to, "Show master seed not allowed") message = "Your unique private key:" message += "
%s
" % self.user.master_seed message += "(Save it, you can access your account using this information)" self.cmd("notification", ["info", message]) # Logout user def actionUserLogout(self, to): if "ADMIN" not in self.site.settings["permissions"]: return self.response(to, "Logout not allowed") message = "You have been logged out. Login to another account" message += "" self.cmd("notification", ["done", message, 1000000]) # 1000000 = Show ~forever :) # Delete from user_manager user_manager = sys.modules["User.UserManager"].user_manager if self.user.master_address in user_manager.users: if not config.multiuser_local: del user_manager.users[self.user.master_address] self.response(to, "Successful logout") else: self.response(to, "User not found") # Show login form def actionUserLoginForm(self, to): self.cmd("prompt", ["Login
Your private key:", "password", "Login"], self.responseUserLogin) # Login form submit def responseUserLogin(self, master_seed): user_manager = sys.modules["User.UserManager"].user_manager user = user_manager.get(CryptBitcoin.privatekeyToAddress(master_seed)) if not user: user = user_manager.create(master_seed=master_seed) if user.master_address: message = "Successfull login, reloading page..." message += "" % user.master_address message += "" self.cmd("notification", ["done", message]) else: self.cmd("notification", ["error", "Error: Invalid master seed"]) self.actionUserLoginForm(0) def hasCmdPermission(self, cmd): cmd = cmd[0].lower() + cmd[1:] if not config.multiuser_local and self.user.master_address not in local_master_addresses and cmd in self.multiuser_denied_cmds: self.cmd("notification", ["info", "This function is disabled on this proxy!"]) return False else: return super(UiWebsocketPlugin, self).hasCmdPermission(cmd) def actionCertAdd(self, *args, **kwargs): super(UiWebsocketPlugin, self).actionCertAdd(*args, **kwargs) master_seed = self.user.master_seed message = "" message += "Hello, welcome to ZeroProxy!
A new, unique account created for you:
" message += "
" + master_seed + "
" message += "
This is your private key, save it, so you can login next time.
Without this key, your registered account will be lost forever!

" message += "Ok, Saved it!

" message += "This site allows you to browse ZeroNet content, but if you want to secure your account
" message += "and help to make a better network, then please run your own ZeroNet client.
" self.cmd("notification", ["info", message]) def actionPermissionAdd(self, to, permission): if permission == "NOSANDBOX": self.cmd("notification", ["info", "You can't disable sandbox on this proxy!"]) self.response(to, {"error": "Denied by proxy"}) return False else: return super(UiWebsocketPlugin, self).actionPermissionAdd(to, permission) @PluginManager.registerTo("ConfigPlugin") class ConfigPlugin(object): def createArguments(self): group = self.parser.add_argument_group("Multiuser plugin") group.add_argument('--multiuser_local', help="Enable unsafe Ui functions and write users to disk", action='store_true') group.add_argument('--multiuser_no_new_sites', help="Denies adding new sites by normal users", action='store_true') return super(ConfigPlugin, self).createArguments()