From 9fa05d6e1fff10cc91768a129d825f3075dda636 Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Mon, 4 Nov 2019 04:52:38 -0600 Subject: [PATCH] added site creator command --- onionr/httpapi/onionrsitesapi/sitefiles.py | 17 +++++---- onionr/onionrblocks/insert.py | 3 +- onionr/onionrcommands/parser/__init__.py | 4 ++- onionr/onionrcommands/parser/arguments.py | 4 +-- onionr/onionrcommands/sitecreator.py | 40 ++++++++++++++++++++++ onionr/onionrcrypto/signing/__init__.py | 1 + onionr/onionrtypes/__init__.py | 4 ++- 7 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 onionr/onionrcommands/sitecreator.py diff --git a/onionr/httpapi/onionrsitesapi/sitefiles.py b/onionr/httpapi/onionrsitesapi/sitefiles.py index 7ce01964..5637abd7 100644 --- a/onionr/httpapi/onionrsitesapi/sitefiles.py +++ b/onionr/httpapi/onionrsitesapi/sitefiles.py @@ -1,4 +1,4 @@ -from typing import Union +from typing import Union, Tuple import tarfile import io import os @@ -6,8 +6,11 @@ import os from coredb import blockmetadb from onionrblocks import onionrblockapi from onionrblocks import insert -from onionrtypes import UserID, DeterministicKeyPassphrase # Import types. Just for type hiting -from onionrcrypto import generate + +# Import types. Just for type hiting +from onionrtypes import UserID, DeterministicKeyPassphrase, BlockHash + +from onionrcrypto import generate_deterministic def find_site_gzip(user_id: str)->str: sites = blockmetadb.get_blocks_by_type('osite') @@ -25,8 +28,8 @@ def get_file(user_id, file)->Union[bytes, None]: return site.extractfile(file) return None -def create_site(admin_pass: DeterministicKeyPassphrase, directory:str='.')->UserID: - public_key, private_key = generate.generate_deterministic(admin_pass) +def create_site(admin_pass: DeterministicKeyPassphrase, directory:str='.')->Tuple[UserID, BlockHash]: + public_key, private_key = generate_deterministic(admin_pass) raw_tar = io.BytesIO() @@ -36,6 +39,6 @@ def create_site(admin_pass: DeterministicKeyPassphrase, directory:str='.')->User raw_tar.seek(0) - insert.insert(raw_tar.read()) + block_hash = insert(raw_tar.read(), signing_key=private_key) - return public_key \ No newline at end of file + return (public_key, block_hash) diff --git a/onionr/onionrblocks/insert.py b/onionr/onionrblocks/insert.py index 65b2befd..dbc9c272 100644 --- a/onionr/onionrblocks/insert.py +++ b/onionr/onionrblocks/insert.py @@ -26,7 +26,8 @@ def insert_block(data: Union[str, bytes], header: str ='txt', our_private_key = crypto.priv_key our_pub_key = crypto.pub_key - if signingKey != '': + if signing_key != '': + # if it was specified to use an alternative private key our_private_key = signing_key our_pub_key = crypto.cryptoutils.get_pub_key_from_priv(our_private_key) diff --git a/onionr/onionrcommands/parser/__init__.py b/onionr/onionrcommands/parser/__init__.py index 69285b25..1d45cca2 100644 --- a/onionr/onionrcommands/parser/__init__.py +++ b/onionr/onionrcommands/parser/__init__.py @@ -74,7 +74,9 @@ def register(): try: if cmd != 'start': os.chdir(os.environ['ORIG_ONIONR_RUN_DIR']) except KeyError: pass - arguments.get_func(cmd)() + try: + arguments.get_func(cmd)() + except KeyboardInterrupt: pass except onionrexceptions.NotFound: if not register_plugin_commands(cmd) and not is_help_cmd: recommend.recommend() diff --git a/onionr/onionrcommands/parser/arguments.py b/onionr/onionrcommands/parser/arguments.py index e9b0df49..3d8c8c55 100644 --- a/onionr/onionrcommands/parser/arguments.py +++ b/onionr/onionrcommands/parser/arguments.py @@ -30,7 +30,7 @@ from .. import softreset # command to delete onionr blocks from .. import restartonionr # command to restart Onionr from .. import runtimetestcmd from .. import motdcreator -from httpapi import onionrsitesapi +from .. import sitecreator import onionrexceptions from onionrutils import importnewblocks # func to import new blocks @@ -50,7 +50,7 @@ def get_arguments()->dict: ('openhome', 'gui', 'openweb', 'open-home', 'open-web'): openwebinterface.open_home, ('get-url', 'url', 'get-web'): openwebinterface.get_url, ('addhtml', 'add-html'): filecommands.add_html, - ('addsite', 'add-site'): onionrsitesapi.sitefiles.create_site, + ('addsite', 'add-site', 'update-site', 'updatesite'): sitecreator.create_multipage_site, ('addfile', 'add-file'): filecommands.add_file, ('get-file', 'getfile'): filecommands.get_file, ('export-block', 'exportblock'): exportblocks.export_block, diff --git a/onionr/onionrcommands/sitecreator.py b/onionr/onionrcommands/sitecreator.py new file mode 100644 index 00000000..85bd3f3a --- /dev/null +++ b/onionr/onionrcommands/sitecreator.py @@ -0,0 +1,40 @@ +import sys +import getpass + +from httpapi import onionrsitesapi +import onionrexceptions +import logger +from etc import onionrvalues + +def create_multipage_site(): + error_encountered = False + try: + directory = sys.argv[2] + except IndexError: + directory = '.' + try: + passphrase = sys.argv[3] + except IndexError: + logger.warn('''It is critical that this passphrase is long. +If you want to update your site later you must remember the passphrase.''', terminal=True) + logger.info(f'Please enter a site passphrase of at least {onionrvalues.PASSWORD_LENGTH} characters.', terminal=True) + passphrase = getpass.getpass() + logger.info('Confirm:', terminal=True) + confirm = getpass.getpass() + if passphrase != confirm: + logger.error('Passphrases do not match', terminal=True) + error_encountered = True + + if len(passphrase) < onionrvalues.PASSWORD_LENGTH: + error_encountered = True + logger.error(f'Passphrase must be at least {onionrvalues.PASSWORD_LENGTH} characters.', terminal=True) + + if error_encountered: + sys.exit(1) + + results = onionrsitesapi.sitefiles.create_site(passphrase, directory=directory) + results = (results[0].replace('=', ''), results[1]) + logger.info(f'Site address {results[0]}', terminal=True) + logger.info(f'Block for this version {results[1]}', terminal=True) + +create_multipage_site.onionr_help = "[directory path (default relative)] - packages a whole directory and makes it available as an Onionr site." diff --git a/onionr/onionrcrypto/signing/__init__.py b/onionr/onionrcrypto/signing/__init__.py index d7c9d748..9e138aff 100644 --- a/onionr/onionrcrypto/signing/__init__.py +++ b/onionr/onionrcrypto/signing/__init__.py @@ -6,6 +6,7 @@ import nacl.encoding, nacl.signing, nacl.exceptions from onionrutils import bytesconverter from onionrutils import mnemonickeys import logger + def ed_sign(data, key, encodeResult=False): '''Ed25519 sign data''' key = unpaddedbase32.repad(bytesconverter.str_to_bytes(key)) diff --git a/onionr/onionrtypes/__init__.py b/onionr/onionrtypes/__init__.py index a1dbbf95..f64a33f5 100644 --- a/onionr/onionrtypes/__init__.py +++ b/onionr/onionrtypes/__init__.py @@ -3,4 +3,6 @@ from typing import NewType UserID = NewType('UserID', str) UserIDSecretKey = NewType('UserIDSecretKey', str) -DeterministicKeyPassphrase = NewType('DeterministicKeyPassphrase', str) \ No newline at end of file +DeterministicKeyPassphrase = NewType('DeterministicKeyPassphrase', str) + +BlockHash = NewType('BlockHash', str) \ No newline at end of file