diff --git a/onionr/communicator.py b/onionr/communicator.py index e958d387..e9eeb28f 100755 --- a/onionr/communicator.py +++ b/onionr/communicator.py @@ -22,10 +22,12 @@ import sys, os, time import core, config, logger, onionr import onionrexceptions, onionrpeers, onionrevents as events, onionrplugins as plugins, onionrblockapi as block -from communicatorutils import onionrdaemontools, servicecreator, onionrcommunicatortimers +from communicatorutils import servicecreator, onionrcommunicatortimers from communicatorutils import downloadblocks, lookupblocks, lookupadders from communicatorutils import servicecreator, connectnewpeers, uploadblocks -from communicatorutils import daemonqueuehandler, announcenode +from communicatorutils import daemonqueuehandler, announcenode, deniableinserts +from communicatorutils import cooldownpeer, housekeeping, netcheck +from etc import humanreadabletime import onionrservices, onionr, onionrproofs OnionrCommunicatorTimers = onionrcommunicatortimers.OnionrCommunicatorTimers @@ -88,10 +90,6 @@ class OnionrCommunicatorDaemon: # Loads in and starts the enabled plugins plugins.reload() - # daemon tools are misc daemon functions, e.g. announce to online peers - # intended only for use by OnionrCommunicatorDaemon - self.daemonTools = onionrdaemontools.DaemonTools(self) - # time app started running for info/statistics purposes self.startTime = self._core._utils.getEpoch() @@ -111,13 +109,13 @@ class OnionrCommunicatorDaemon: OnionrCommunicatorTimers(self, self.clearOfflinePeer, 58) # Timer to cleanup old blocks - blockCleanupTimer = OnionrCommunicatorTimers(self, self.daemonTools.cleanOldBlocks, 65) + blockCleanupTimer = OnionrCommunicatorTimers(self, housekeeping.clean_old_blocks, 65, myArgs=[self]) # Timer to discover new peers OnionrCommunicatorTimers(self, self.lookupAdders, 60, requiresPeer=True) # Timer for adjusting which peers we actively communicate to at any given time, to avoid over-using peers - OnionrCommunicatorTimers(self, self.daemonTools.cooldownPeer, 30, requiresPeer=True) + OnionrCommunicatorTimers(self, cooldownpeer.cooldown_peer, 30, myArgs=[self], requiresPeer=True) # Timer to read the upload queue and upload the entries to peers OnionrCommunicatorTimers(self, self.uploadBlock, 10, requiresPeer=True, maxThreads=1) @@ -133,17 +131,17 @@ class OnionrCommunicatorDaemon: self.services = onionrservices.OnionrServices(self._core) self.active_services = [] self.service_greenlets = [] - OnionrCommunicatorTimers(self, servicecreator.service_creator, 5, maxThreads=50, myArgs=(self,)) + OnionrCommunicatorTimers(self, servicecreator.service_creator, 5, maxThreads=50, myArgs=[self]) else: self.services = None # This timer creates deniable blocks, in an attempt to further obfuscate block insertion metadata if config.get('general.insert_deniable_blocks', True): - deniableBlockTimer = OnionrCommunicatorTimers(self, self.daemonTools.insertDeniableBlock, 180, requiresPeer=True, maxThreads=1) + deniableBlockTimer = OnionrCommunicatorTimers(self, deniableinserts.insert_deniable_block, 180, myArgs=[self], requiresPeer=True, maxThreads=1) deniableBlockTimer.count = (deniableBlockTimer.frequency - 175) # Timer to check for connectivity, through Tor to various high-profile onion services - netCheckTimer = OnionrCommunicatorTimers(self, self.daemonTools.netCheck, 600) + netCheckTimer = OnionrCommunicatorTimers(self, netcheck.net_check, 600, myArgs=[self]) # Announce the public API server transport address to other nodes if security level allows if config.get('general.security_level', 1) == 0: @@ -157,7 +155,7 @@ class OnionrCommunicatorDaemon: cleanupTimer = OnionrCommunicatorTimers(self, self.peerCleanup, 300, requiresPeer=True) # Timer to cleanup dead ephemeral forward secrecy keys - forwardSecrecyTimer = OnionrCommunicatorTimers(self, self.daemonTools.cleanKeys, 15, maxThreads=1) + forwardSecrecyTimer = OnionrCommunicatorTimers(self, housekeeping.clean_keys, 15, myArgs=[self], maxThreads=1) # Adjust initial timer triggers peerPoolTimer.count = (peerPoolTimer.frequency - 1) @@ -255,7 +253,7 @@ class OnionrCommunicatorDaemon: break else: if len(self.onlinePeers) == 0: - logger.debug('Couldn\'t connect to any peers.' + (' Last node seen %s ago.' % self.daemonTools.humanReadableTime(time.time() - self.lastNodeSeen) if not self.lastNodeSeen is None else '')) + logger.debug('Couldn\'t connect to any peers.' + (' Last node seen %s ago.' % humanreadabletime.human_readable_time(time.time() - self.lastNodeSeen) if not self.lastNodeSeen is None else '')) else: self.lastNodeSeen = time.time() self.decrementThreadCount('getOnlinePeers') @@ -346,7 +344,7 @@ class OnionrCommunicatorDaemon: def heartbeat(self): '''Show a heartbeat debug message''' - logger.debug('Heartbeat. Node running for %s.' % self.daemonTools.humanReadableTime(self.getUptime())) + logger.debug('Heartbeat. Node running for %s.' % humanreadabletime.human_readable_time(self.getUptime())) self.decrementThreadCount('heartbeat') def daemonCommands(self): @@ -379,10 +377,17 @@ class OnionrCommunicatorDaemon: self.decrementThreadCount('detectAPICrash') def runCheck(self): - if self.daemonTools.runCheck(): + if run_file_exists(self): logger.debug('Status check; looks good.') self.decrementThreadCount('runCheck') def startCommunicator(onionrInst, proxyPort): - OnionrCommunicatorDaemon(onionrInst, proxyPort) \ No newline at end of file + OnionrCommunicatorDaemon(onionrInst, proxyPort) + +def run_file_exists(daemon): + if os.path.isfile(daemon._core.dataDir + '.runcheck'): + os.remove(daemon._core.dataDir + '.runcheck') + return True + + return False \ No newline at end of file diff --git a/onionr/communicatorutils/README.md b/onionr/communicatorutils/README.md index 5f37a122..393328c3 100644 --- a/onionr/communicatorutils/README.md +++ b/onionr/communicatorutils/README.md @@ -8,15 +8,23 @@ announcenode.py: Uses a communicator instance to announce our transport address connectnewpeers.py: takes a communicator instance and has it connect to as many peers as needed, and/or to a new specified peer. +cooldownpeer.py: randomly selects a connected peer in a communicator and disconnects them for the purpose of security and network balancing. + daemonqueuehandler.py: checks for new commands in the daemon queue and processes them accordingly. +deniableinserts.py: insert fake blocks with the communicator for plausible deniability + downloadblocks.py: iterates a communicator instance's block download queue and attempts to download the blocks from online peers +housekeeping.py: cleans old blocks and forward secrecy keys + lookupadders.py: ask connected peers to share their list of peer transport addresses -onionrcommunicataortimers.py: create a timer for a function to be launched on an interval. Control how many possible instances of a timer may be running a function at once and control if the timer should be ran in a thread or not. +lookupblocks.py: lookup new blocks from connected peers from the communicator -onionrdaemontools.py: contains the DaemonTools class which has a lot of etc functions useful for the communicator. Deprecated. +netcheck.py: check if the node is online based on communicator status and onion server ping results + +onionrcommunicataortimers.py: create a timer for a function to be launched on an interval. Control how many possible instances of a timer may be running a function at once and control if the timer should be ran in a thread or not. proxypicker.py: returns a string name for the appropriate proxy to be used with a particular peer transport address. diff --git a/onionr/communicatorutils/announcenode.py b/onionr/communicatorutils/announcenode.py index 6ba136ba..e3f7d268 100644 --- a/onionr/communicatorutils/announcenode.py +++ b/onionr/communicatorutils/announcenode.py @@ -80,5 +80,5 @@ def announce_node(daemon): retData = True daemon._core.setAddressInfo(peer, 'introduced', 1) daemon._core.setAddressInfo(peer, 'powValue', data['random']) - daemon.decrementThreadCount('announceNode') + daemon.decrementThreadCount('announce_node') return retData \ No newline at end of file diff --git a/onionr/communicatorutils/cooldownpeer.py b/onionr/communicatorutils/cooldownpeer.py new file mode 100644 index 00000000..26cf2dd9 --- /dev/null +++ b/onionr/communicatorutils/cooldownpeer.py @@ -0,0 +1,51 @@ +''' + Onionr - Private P2P Communication + + Select a random online peer in a communicator instance and have them "cool down" +''' +''' + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +''' +def cooldown_peer(comm_inst): + '''Randomly add an online peer to cooldown, so we can connect a new one''' + onlinePeerAmount = len(comm_inst.onlinePeers) + minTime = 300 + cooldownTime = 600 + toCool = '' + tempConnectTimes = dict(comm_inst.connectTimes) + + # Remove peers from cooldown that have been there long enough + tempCooldown = dict(comm_inst.cooldownPeer) + for peer in tempCooldown: + if (comm_inst._core._utils.getEpoch() - tempCooldown[peer]) >= cooldownTime: + del comm_inst.cooldownPeer[peer] + + # Cool down a peer, if we have max connections alive for long enough + if onlinePeerAmount >= comm_inst._core.config.get('peers.max_connect', 10, save = True): + finding = True + + while finding: + try: + toCool = min(tempConnectTimes, key=tempConnectTimes.get) + if (comm_inst._core._utils.getEpoch() - tempConnectTimes[toCool]) < minTime: + del tempConnectTimes[toCool] + else: + finding = False + except ValueError: + break + else: + comm_inst.removeOnlinePeer(toCool) + comm_inst.cooldownPeer[toCool] = comm_inst._core._utils.getEpoch() + + comm_inst.decrementThreadCount('cooldown_peer') \ No newline at end of file diff --git a/onionr/communicatorutils/deniableinserts.py b/onionr/communicatorutils/deniableinserts.py new file mode 100644 index 00000000..f993e6d0 --- /dev/null +++ b/onionr/communicatorutils/deniableinserts.py @@ -0,0 +1,31 @@ +''' + Onionr - Private P2P Communication + + Use the communicator to insert fake mail messages +''' +''' + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +''' +import secrets +from etc import onionrvalues +def insert_deniable_block(comm_inst): + '''Insert a fake block in order to make it more difficult to track real blocks''' + fakePeer = '' + chance = 10 + if secrets.randbelow(chance) == (chance - 1): + # This assumes on the libsodium primitives to have key-privacy + fakePeer = onionrvalues.DENIABLE_PEER_ADDRESS + data = secrets.token_hex(secrets.randbelow(1024) + 1) + comm_inst._core.insertBlock(data, header='pm', encryptType='asym', asymPeer=fakePeer, meta={'subject': 'foo'}) + comm_inst.decrementThreadCount('insert_deniable_block') \ No newline at end of file diff --git a/onionr/communicatorutils/housekeeping.py b/onionr/communicatorutils/housekeeping.py new file mode 100644 index 00000000..829564ab --- /dev/null +++ b/onionr/communicatorutils/housekeeping.py @@ -0,0 +1,59 @@ +''' + Onionr - Private P2P Communication + + Cleanup old Onionr blocks and forward secrecy keys using the communicator. Ran from a timer usually +''' +''' + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +''' +import sqlite3 +import logger +from onionrusers import onionrusers +def clean_old_blocks(comm_inst): + '''Delete old blocks if our disk allocation is full/near full, and also expired blocks''' + + # Delete expired blocks + for bHash in comm_inst._core.getExpiredBlocks(): + comm_inst._core._blacklist.addToDB(bHash) + comm_inst._core.removeBlock(bHash) + logger.info('Deleted block: %s' % (bHash,)) + + while comm_inst._core._utils.storageCounter.isFull(): + oldest = comm_inst._core.getBlockList()[0] + comm_inst._core._blacklist.addToDB(oldest) + comm_inst._core.removeBlock(oldest) + logger.info('Deleted block: %s' % (oldest,)) + + comm_inst.decrementThreadCount('clean_old_blocks') + +def clean_keys(comm_inst): + '''Delete expired forward secrecy keys''' + conn = sqlite3.connect(comm_inst._core.peerDB, timeout=10) + c = conn.cursor() + time = comm_inst._core._utils.getEpoch() + deleteKeys = [] + + for entry in c.execute("SELECT * FROM forwardKeys WHERE expire <= ?", (time,)): + logger.debug('Forward key: %s' % entry[1]) + deleteKeys.append(entry[1]) + + for key in deleteKeys: + logger.debug('Deleting forward key %s' % key) + c.execute("DELETE from forwardKeys where forwardKey = ?", (key,)) + conn.commit() + conn.close() + + onionrusers.deleteExpiredKeys(comm_inst._core) + + comm_inst.decrementThreadCount('clean_keys') \ No newline at end of file diff --git a/onionr/communicatorutils/netcheck.py b/onionr/communicatorutils/netcheck.py new file mode 100644 index 00000000..36a3a304 --- /dev/null +++ b/onionr/communicatorutils/netcheck.py @@ -0,0 +1,32 @@ +''' + Onionr - Private P2P Communication + + Determine if our node is able to use Tor based on the status of a communicator instance + and the result of pinging onion http servers +''' +''' + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +''' +import logger +from utils import netutils +def net_check(comm_inst): + '''Check if we are connected to the internet or not when we can't connect to any peers''' + if len(comm_inst.onlinePeers) == 0: + if not netutils.checkNetwork(comm_inst._core._utils, torPort=comm_inst.proxyPort): + if not comm_inst.shutdown: + logger.warn('Network check failed, are you connected to the Internet, and is Tor working?') + comm_inst.isOnline = False + else: + comm_inst.isOnline = True + comm_inst.decrementThreadCount('net_check') \ No newline at end of file diff --git a/onionr/communicatorutils/onionrdaemontools.py b/onionr/communicatorutils/onionrdaemontools.py deleted file mode 100755 index c0e74df3..00000000 --- a/onionr/communicatorutils/onionrdaemontools.py +++ /dev/null @@ -1,158 +0,0 @@ -''' - Onionr - Private P2P Communication - - Contains the DaemonTools class -''' -''' - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -''' - -# MODULE DEPRECATED - -import onionrexceptions, onionrpeers, onionrproofs, logger -import base64, sqlite3, os -from dependencies import secrets -from utils import netutils -from onionrusers import onionrusers -from etc import onionrvalues -ov = onionrvalues.OnionrValues() - -class DaemonTools: - ''' - Class intended for use by Onionr Communicator - ''' - def __init__(self, daemon): - self.daemon = daemon - self.announceProgress = {} - self.announceCache = {} - - def netCheck(self): - '''Check if we are connected to the internet or not when we can't connect to any peers''' - if len(self.daemon.onlinePeers) == 0: - if not netutils.checkNetwork(self.daemon._core._utils, torPort=self.daemon.proxyPort): - if not self.daemon.shutdown: - logger.warn('Network check failed, are you connected to the Internet, and is Tor working?') - self.daemon.isOnline = False - else: - self.daemon.isOnline = True - self.daemon.decrementThreadCount('netCheck') - - def cleanOldBlocks(self): - '''Delete old blocks if our disk allocation is full/near full, and also expired blocks''' - - # Delete expired blocks - for bHash in self.daemon._core.getExpiredBlocks(): - self.daemon._core._blacklist.addToDB(bHash) - self.daemon._core.removeBlock(bHash) - logger.info('Deleted block: %s' % (bHash,)) - - while self.daemon._core._utils.storageCounter.isFull(): - oldest = self.daemon._core.getBlockList()[0] - self.daemon._core._blacklist.addToDB(oldest) - self.daemon._core.removeBlock(oldest) - logger.info('Deleted block: %s' % (oldest,)) - - self.daemon.decrementThreadCount('cleanOldBlocks') - - def cleanKeys(self): - '''Delete expired forward secrecy keys''' - conn = sqlite3.connect(self.daemon._core.peerDB, timeout=10) - c = conn.cursor() - time = self.daemon._core._utils.getEpoch() - deleteKeys = [] - - for entry in c.execute("SELECT * FROM forwardKeys WHERE expire <= ?", (time,)): - logger.debug('Forward key: %s' % entry[1]) - deleteKeys.append(entry[1]) - - for key in deleteKeys: - logger.debug('Deleting forward key %s' % key) - c.execute("DELETE from forwardKeys where forwardKey = ?", (key,)) - conn.commit() - conn.close() - - onionrusers.deleteExpiredKeys(self.daemon._core) - - self.daemon.decrementThreadCount('cleanKeys') - - def cooldownPeer(self): - '''Randomly add an online peer to cooldown, so we can connect a new one''' - onlinePeerAmount = len(self.daemon.onlinePeers) - minTime = 300 - cooldownTime = 600 - toCool = '' - tempConnectTimes = dict(self.daemon.connectTimes) - - # Remove peers from cooldown that have been there long enough - tempCooldown = dict(self.daemon.cooldownPeer) - for peer in tempCooldown: - if (self.daemon._core._utils.getEpoch() - tempCooldown[peer]) >= cooldownTime: - del self.daemon.cooldownPeer[peer] - - # Cool down a peer, if we have max connections alive for long enough - if onlinePeerAmount >= self.daemon._core.config.get('peers.max_connect', 10, save = True): - finding = True - - while finding: - try: - toCool = min(tempConnectTimes, key=tempConnectTimes.get) - if (self.daemon._core._utils.getEpoch() - tempConnectTimes[toCool]) < minTime: - del tempConnectTimes[toCool] - else: - finding = False - except ValueError: - break - else: - self.daemon.removeOnlinePeer(toCool) - self.daemon.cooldownPeer[toCool] = self.daemon._core._utils.getEpoch() - - self.daemon.decrementThreadCount('cooldownPeer') - - def runCheck(self): - if os.path.isfile(self.daemon._core.dataDir + '.runcheck'): - os.remove(self.daemon._core.dataDir + '.runcheck') - return True - - return False - - def humanReadableTime(self, seconds): - build = '' - - units = { - 'year' : 31557600, - 'month' : (31557600 / 12), - 'day' : 86400, - 'hour' : 3600, - 'minute' : 60, - 'second' : 1 - } - - for unit in units: - amnt_unit = int(seconds / units[unit]) - if amnt_unit >= 1: - seconds -= amnt_unit * units[unit] - build += '%s %s' % (amnt_unit, unit) + ('s' if amnt_unit != 1 else '') + ' ' - - return build.strip() - - def insertDeniableBlock(self): - '''Insert a fake block in order to make it more difficult to track real blocks''' - fakePeer = '' - chance = 10 - if secrets.randbelow(chance) == (chance - 1): - # This assumes on the libsodium primitives to have key-privacy - fakePeer = 'OVPCZLOXD6DC5JHX4EQ3PSOGAZ3T24F75HQLIUZSDSMYPEOXCPFA====' - data = secrets.token_hex(secrets.randbelow(1024) + 1) - self.daemon._core.insertBlock(data, header='pm', encryptType='asym', asymPeer=fakePeer, meta={'subject': 'foo'}) - self.daemon.decrementThreadCount('insertDeniableBlock') \ No newline at end of file diff --git a/onionr/core.py b/onionr/core.py index 58c95d9f..53d834f6 100755 --- a/onionr/core.py +++ b/onionr/core.py @@ -808,7 +808,7 @@ class Core: self._utils.processBlockMetadata(retData) if retData != False: - if plaintextPeer == 'OVPCZLOXD6DC5JHX4EQ3PSOGAZ3T24F75HQLIUZSDSMYPEOXCPFA====': + if plaintextPeer == onionrvalues.DENIABLE_PEER_ADDRESS: events.event('insertdeniable', {'content': plaintext, 'meta': plaintextMeta, 'hash': retData, 'peer': self._utils.bytesToStr(asymPeer)}, onionr = self.onionrInst, threaded = True) else: events.event('insertblock', {'content': plaintext, 'meta': plaintextMeta, 'hash': retData, 'peer': self._utils.bytesToStr(asymPeer)}, onionr = self.onionrInst, threaded = True) diff --git a/onionr/dependencies/secrets.py b/onionr/dependencies/secrets.py deleted file mode 100755 index 9b2eb61b..00000000 --- a/onionr/dependencies/secrets.py +++ /dev/null @@ -1,331 +0,0 @@ -"""Generate cryptographically strong pseudo-random numbers suitable for -managing secrets such as account authentication, tokens, and similar. - -See PEP 506 for more information. -https://www.python.org/dev/peps/pep-0506/ - - -A. HISTORY OF THE SOFTWARE -========================== - -Python was created in the early 1990s by Guido van Rossum at Stichting -Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands -as a successor of a language called ABC. Guido remains Python's -principal author, although it includes many contributions from others. - -In 1995, Guido continued his work on Python at the Corporation for -National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) -in Reston, Virginia where he released several versions of the -software. - -In May 2000, Guido and the Python core development team moved to -BeOpen.com to form the BeOpen PythonLabs team. In October of the same -year, the PythonLabs team moved to Digital Creations, which became -Zope Corporation. In 2001, the Python Software Foundation (PSF, see -https://www.python.org/psf/) was formed, a non-profit organization -created specifically to own Python-related Intellectual Property. -Zope Corporation was a sponsoring member of the PSF. - -All Python releases are Open Source (see http://www.opensource.org for -the Open Source Definition). Historically, most, but not all, Python -releases have also been GPL-compatible; the table below summarizes -the various releases. - - Release Derived Year Owner GPL- - from compatible? (1) - - 0.9.0 thru 1.2 1991-1995 CWI yes - 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes - 1.6 1.5.2 2000 CNRI no - 2.0 1.6 2000 BeOpen.com no - 1.6.1 1.6 2001 CNRI yes (2) - 2.1 2.0+1.6.1 2001 PSF no - 2.0.1 2.0+1.6.1 2001 PSF yes - 2.1.1 2.1+2.0.1 2001 PSF yes - 2.1.2 2.1.1 2002 PSF yes - 2.1.3 2.1.2 2002 PSF yes - 2.2 and above 2.1.1 2001-now PSF yes - -Footnotes: - -(1) GPL-compatible doesn't mean that we're distributing Python under - the GPL. All Python licenses, unlike the GPL, let you distribute - a modified version without making your changes open source. The - GPL-compatible licenses make it possible to combine Python with - other software that is released under the GPL; the others don't. - -(2) According to Richard Stallman, 1.6.1 is not GPL-compatible, - because its license has a choice of law clause. According to - CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 - is "not incompatible" with the GPL. - -Thanks to the many outside volunteers who have worked under Guido's -direction to make these releases possible. - - -B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON -=============================================================== - -PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 --------------------------------------------- - -1. This LICENSE AGREEMENT is between the Python Software Foundation -("PSF"), and the Individual or Organization ("Licensee") accessing and -otherwise using this software ("Python") in source or binary form and -its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, PSF hereby -grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, -analyze, test, perform and/or display publicly, prepare derivative works, -distribute, and otherwise use Python alone or in any derivative version, -provided, however, that PSF's License Agreement and PSF's notice of copyright, -i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 Python Software Foundation; All -Rights Reserved" are retained in Python alone or in any derivative version -prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python. - -4. PSF is making Python available to Licensee on an "AS IS" -basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any -relationship of agency, partnership, or joint venture between PSF and -Licensee. This License Agreement does not grant permission to use PSF -trademarks or trade name in a trademark sense to endorse or promote -products or services of Licensee, or any third party. - -8. By copying, installing or otherwise using Python, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. - - -BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 -------------------------------------------- - -BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 - -1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an -office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the -Individual or Organization ("Licensee") accessing and otherwise using -this software in source or binary form and its associated -documentation ("the Software"). - -2. Subject to the terms and conditions of this BeOpen Python License -Agreement, BeOpen hereby grants Licensee a non-exclusive, -royalty-free, world-wide license to reproduce, analyze, test, perform -and/or display publicly, prepare derivative works, distribute, and -otherwise use the Software alone or in any derivative version, -provided, however, that the BeOpen Python License is retained in the -Software, alone or in any derivative version prepared by Licensee. - -3. BeOpen is making the Software available to Licensee on an "AS IS" -basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE -SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS -AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY -DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -5. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -6. This License Agreement shall be governed by and interpreted in all -respects by the law of the State of California, excluding conflict of -law provisions. Nothing in this License Agreement shall be deemed to -create any relationship of agency, partnership, or joint venture -between BeOpen and Licensee. This License Agreement does not grant -permission to use BeOpen trademarks or trade names in a trademark -sense to endorse or promote products or services of Licensee, or any -third party. As an exception, the "BeOpen Python" logos available at -http://www.pythonlabs.com/logos.html may be used according to the -permissions granted on that web page. - -7. By copying, installing or otherwise using the software, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. - - -CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 ---------------------------------------- - -1. This LICENSE AGREEMENT is between the Corporation for National -Research Initiatives, having an office at 1895 Preston White Drive, -Reston, VA 20191 ("CNRI"), and the Individual or Organization -("Licensee") accessing and otherwise using Python 1.6.1 software in -source or binary form and its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, CNRI -hereby grants Licensee a nonexclusive, royalty-free, world-wide -license to reproduce, analyze, test, perform and/or display publicly, -prepare derivative works, distribute, and otherwise use Python 1.6.1 -alone or in any derivative version, provided, however, that CNRI's -License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) -1995-2001 Corporation for National Research Initiatives; All Rights -Reserved" are retained in Python 1.6.1 alone or in any derivative -version prepared by Licensee. Alternately, in lieu of CNRI's License -Agreement, Licensee may substitute the following text (omitting the -quotes): "Python 1.6.1 is made available subject to the terms and -conditions in CNRI's License Agreement. This Agreement together with -Python 1.6.1 may be located on the Internet using the following -unique, persistent identifier (known as a handle): 1895.22/1013. This -Agreement may also be obtained from a proxy server on the Internet -using the following URL: http://hdl.handle.net/1895.22/1013". - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python 1.6.1 or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python 1.6.1. - -4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" -basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. This License Agreement shall be governed by the federal -intellectual property law of the United States, including without -limitation the federal copyright law, and, to the extent such -U.S. federal law does not apply, by the law of the Commonwealth of -Virginia, excluding Virginia's conflict of law provisions. -Notwithstanding the foregoing, with regard to derivative works based -on Python 1.6.1 that incorporate non-separable material that was -previously distributed under the GNU General Public License (GPL), the -law of the Commonwealth of Virginia shall govern this License -Agreement only as to issues arising under or with respect to -Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this -License Agreement shall be deemed to create any relationship of -agency, partnership, or joint venture between CNRI and Licensee. This -License Agreement does not grant permission to use CNRI trademarks or -trade name in a trademark sense to endorse or promote products or -services of Licensee, or any third party. - -8. By clicking on the "ACCEPT" button where indicated, or by copying, -installing or otherwise using Python 1.6.1, Licensee agrees to be -bound by the terms and conditions of this License Agreement. - - ACCEPT - - -CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 --------------------------------------------------- - -Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, -The Netherlands. All rights reserved. - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Stichting Mathematisch -Centrum or CWI not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO -THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE -FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -""" - -__all__ = ['choice', 'randbelow', 'randbits', 'SystemRandom', - 'token_bytes', 'token_hex', 'token_urlsafe', - 'compare_digest', - ] - - -import base64 -import binascii -import os - -from hmac import compare_digest -from random import SystemRandom - -_sysrand = SystemRandom() - -randbits = _sysrand.getrandbits -choice = _sysrand.choice - -def randbelow(exclusive_upper_bound): - """Return a random int in the range [0, n).""" - if exclusive_upper_bound <= 0: - raise ValueError("Upper bound must be positive.") - return _sysrand._randbelow(exclusive_upper_bound) - -DEFAULT_ENTROPY = 32 # number of bytes to return by default - -def token_bytes(nbytes=None): - """Return a random byte string containing *nbytes* bytes. - - If *nbytes* is ``None`` or not supplied, a reasonable - default is used. - - >>> token_bytes(16) #doctest:+SKIP - b'\\xebr\\x17D*t\\xae\\xd4\\xe3S\\xb6\\xe2\\xebP1\\x8b' - - """ - if nbytes is None: - nbytes = DEFAULT_ENTROPY - return os.urandom(nbytes) - -def token_hex(nbytes=None): - """Return a random text string, in hexadecimal. - - The string has *nbytes* random bytes, each byte converted to two - hex digits. If *nbytes* is ``None`` or not supplied, a reasonable - default is used. - - >>> token_hex(16) #doctest:+SKIP - 'f9bf78b9a18ce6d46a0cd2b0b86df9da' - - """ - return binascii.hexlify(token_bytes(nbytes)).decode('ascii') - -def token_urlsafe(nbytes=None): - """Return a random URL-safe text string, in Base64 encoding. - - The string has *nbytes* random bytes. If *nbytes* is ``None`` - or not supplied, a reasonable default is used. - - >>> token_urlsafe(16) #doctest:+SKIP - 'Drmhze6EPcv0fN_81Bj-nA' - - """ - tok = token_bytes(nbytes) - return base64.urlsafe_b64encode(tok).rstrip(b'=').decode('ascii') - diff --git a/onionr/etc/humanreadabletime.py b/onionr/etc/humanreadabletime.py new file mode 100644 index 00000000..7e3ff3bc --- /dev/null +++ b/onionr/etc/humanreadabletime.py @@ -0,0 +1,38 @@ +''' + Onionr - Private P2P Communication + + human_readable_time takes integer seconds and returns a human readable string +''' +''' + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +''' +def human_readable_time(seconds): + build = '' + + units = { + 'year' : 31557600, + 'month' : (31557600 / 12), + 'day' : 86400, + 'hour' : 3600, + 'minute' : 60, + 'second' : 1 + } + + for unit in units: + amnt_unit = int(seconds / units[unit]) + if amnt_unit >= 1: + seconds -= amnt_unit * units[unit] + build += '%s %s' % (amnt_unit, unit) + ('s' if amnt_unit != 1 else '') + ' ' + + return build.strip() \ No newline at end of file diff --git a/onionr/etc/onionrvalues.py b/onionr/etc/onionrvalues.py index e3e1421d..5df394db 100755 --- a/onionr/etc/onionrvalues.py +++ b/onionr/etc/onionrvalues.py @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . ''' - +DENIABLE_PEER_ADDRESS = "OVPCZLOXD6DC5JHX4EQ3PSOGAZ3T24F75HQLIUZSDSMYPEOXCPFA====" class OnionrValues: def __init__(self): self.passwordLength = 20 diff --git a/onionr/netcontroller.py b/onionr/netcontroller.py index fa64c938..6edbd474 100755 --- a/onionr/netcontroller.py +++ b/onionr/netcontroller.py @@ -17,11 +17,10 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . ''' -import subprocess, os, random, sys, time, signal, base64, socket +import subprocess, os, sys, time, signal, base64, socket from shutil import which import logger, config from onionrblockapi import Block -from dependencies import secrets def getOpenPort(): # taken from (but modified) https://stackoverflow.com/a/2838309 by https://stackoverflow.com/users/133374/albert ccy-by-sa-3 https://creativecommons.org/licenses/by-sa/3.0/ diff --git a/onionr/onionrcrypto.py b/onionr/onionrcrypto.py index 2ce90bf6..dab3e8b7 100755 --- a/onionr/onionrcrypto.py +++ b/onionr/onionrcrypto.py @@ -17,15 +17,10 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . ''' -import os, binascii, base64, hashlib, time, sys, hmac +import os, binascii, base64, hashlib, time, sys, hmac, secrets import nacl.signing, nacl.encoding, nacl.public, nacl.hash, nacl.pwhash, nacl.utils, nacl.secret import logger, onionrproofs import onionrexceptions, keymanager, core -# secrets module was added into standard lib in 3.6+ -if sys.version_info[0] == 3 and sys.version_info[1] < 6: - from dependencies import secrets -elif sys.version_info[0] == 3 and sys.version_info[1] >= 6: - import secrets import config class OnionrCrypto: