diff --git a/onionr/communicator2.py b/onionr/communicator2.py index 38ba2692..9c44ed21 100755 --- a/onionr/communicator2.py +++ b/onionr/communicator2.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 ''' - Onionr - P2P Microblogging Platform & Social network. + Onionr - P2P Anonymous Storage Network This file contains both the OnionrCommunicate class for communcating with peers and code to operate as a daemon, getting commands from the command queue database (see core.Core.daemonQueue) diff --git a/onionr/core.py b/onionr/core.py index 9d97e3f1..f7d36072 100644 --- a/onionr/core.py +++ b/onionr/core.py @@ -1,5 +1,5 @@ ''' - Onionr - P2P Microblogging Platform & Social network + Onionr - P2P Anonymous Storage Network Core Onionr library, useful for external programs. Handles peer & data processing ''' @@ -102,7 +102,7 @@ class Core: conn = sqlite3.connect(self.peerDB) hashID = self._crypto.pubKeyHashID(peerID) c = conn.cursor() - t = (peerID, name, 'unknown', hashID, powID) + t = (peerID, name, 'unknown', hashID, powID, 0) for i in c.execute("SELECT * FROM PEERS where id = '" + peerID + "';"): try: @@ -113,7 +113,7 @@ class Core: pass except IndexError: pass - c.execute('INSERT INTO peers (id, name, dateSeen, pow, hashID) VALUES(?, ?, ?, ?, ?);', t) + c.execute('INSERT INTO peers (id, name, dateSeen, pow, hashID, trust) VALUES(?, ?, ?, ?, ?, ?);', t) conn.commit() conn.close() @@ -403,19 +403,23 @@ class Core: conn.close() return addressList - def listPeers(self, randomOrder=True, getPow=False): + def listPeers(self, randomOrder=True, getPow=False, trust=0): ''' Return a list of public keys (misleading function name) randomOrder determines if the list should be in a random order + trust sets the minimum trust to list ''' conn = sqlite3.connect(self.peerDB) c = conn.cursor() payload = "" + if trust not in (0, 1, 2): + logger.error('Tried to select invalid trust.') + return if randomOrder: - payload = 'SELECT * FROM peers ORDER BY RANDOM();' + payload = 'SELECT * FROM peers where trust >= %s ORDER BY RANDOM();' % (trust,) else: - payload = 'SELECT * FROM peers;' + payload = 'SELECT * FROM peers where trust >= %s;' % (trust,) peerList = [] for i in c.execute(payload): try: diff --git a/onionr/dbcreator.py b/onionr/dbcreator.py index 19a9a7bd..5f3d2c79 100644 --- a/onionr/dbcreator.py +++ b/onionr/dbcreator.py @@ -61,7 +61,6 @@ class DBCreator: ID text not null, name text, adders text, - blockDBHash text, forwardKey text, dateSeen not null, bytesStored int, diff --git a/onionr/onionr.py b/onionr/onionr.py index 1736c3f9..5408b2c4 100755 --- a/onionr/onionr.py +++ b/onionr/onionr.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 ''' - Onionr - P2P Microblogging Platform & Social network. + Onionr - P2P Anonymous Storage Network Onionr is the name for both the protocol and the original/reference software. @@ -32,7 +32,7 @@ import onionrutils from onionrutils import OnionrUtils from netcontroller import NetController from onionrblockapi import Block -import onionrproofs +import onionrproofs, onionrexceptions, onionrusers try: from urllib3.contrib.socks import SOCKSProxyManager @@ -210,7 +210,9 @@ class Onionr: 'getpass': self.printWebPassword, 'get-pass': self.printWebPassword, 'getpasswd': self.printWebPassword, - 'get-passwd': self.printWebPassword + 'get-passwd': self.printWebPassword, + + 'friend': self.friendCmd } self.cmdhelp = { @@ -234,6 +236,7 @@ class Onionr: 'pex': 'exchange addresses with peers (done automatically)', 'blacklist-block': 'deletes a block by hash and permanently removes it from your node', 'introduce': 'Introduce your node to the public Onionr network', + 'friend': '[add|remove] [public key/id]' } # initialize plugins @@ -260,6 +263,41 @@ class Onionr: def getCommands(self): return self.cmds + + def friendCmd(self): + '''List, add, or remove friend(s)''' + friend = '' + try: + action = sys.argv[2] + except IndexError: + logger.info('Syntax: friend add/remove/list [address]') + else: + action = action.lower() + if action == 'list': + for friend in self.onionrCore.listPeers(randomOrder=False, trust=1): + logger.info(friend) + elif action in ('add', 'remove'): + try: + friend = sys.argv[3] + if not self.onionrUtils.validatePubKey(friend): + raise onionrexceptions.InvalidPubkey('Public key is invalid') + if friend not in self.onionrCore.listPeers(): + raise onionrexceptions.KeyNotKnown + friend = onionrusers.OnionrUser(self.onionrCore, friend) + except IndexError: + logger.error('Friend ID is required.') + except onionrexceptions.KeyNotKnown: + logger.error('That peer is not in our database') + else: + if action == 'add': + friend.setTrust(1) + logger.info('Added %s as friend.' % (friend.publicKey,)) + else: + friend.setTrust(0) + logger.info('Removed %s as friend.' % (friend.publicKey,)) + else: + logger.info('Syntax: friend add/remove/list [address]') + def banBlock(self): try: diff --git a/onionr/onionrblacklist.py b/onionr/onionrblacklist.py index 86823283..863ddc37 100644 --- a/onionr/onionrblacklist.py +++ b/onionr/onionrblacklist.py @@ -1,5 +1,5 @@ ''' - Onionr - P2P Microblogging Platform & Social network. + Onionr - P2P Anonymous Storage Network This file handles maintenence of a blacklist database, for blocks and peers ''' diff --git a/onionr/onionrblockapi.py b/onionr/onionrblockapi.py index e255c0ae..97b34730 100644 --- a/onionr/onionrblockapi.py +++ b/onionr/onionrblockapi.py @@ -1,5 +1,5 @@ ''' - Onionr - P2P Microblogging Platform & Social network. + Onionr - P2P Anonymous Storage Network This class contains the OnionrBlocks class which is a class for working with Onionr blocks ''' diff --git a/onionr/onionrcrypto.py b/onionr/onionrcrypto.py index 00c5a604..9e055716 100644 --- a/onionr/onionrcrypto.py +++ b/onionr/onionrcrypto.py @@ -155,26 +155,6 @@ class OnionrCrypto: decrypted = anonBox.decrypt(data, encoder=encoding) return decrypted - def symmetricPeerEncrypt(self, data, peer): - '''Salsa20 encrypt data to peer (with mac) - this function does not accept a key, it is a wrapper for encryption with a peer - ''' - key = self._core.getPeerInfo(4) - if type(key) != bytes: - key = self._core.getPeerInfo(2) - encrypted = self.symmetricEncrypt(data, key, encodedKey=True) - return encrypted - - def symmetricPeerDecrypt(self, data, peer): - '''Salsa20 decrypt data from peer (with mac) - this function does not accept a key, it is a wrapper for encryption with a peer - ''' - key = self._core.getPeerInfo(4) - if type(key) != bytes: - key = self._core.getPeerInfo(2) - decrypted = self.symmetricDecrypt(data, key, encodedKey=True) - return decrypted - def symmetricEncrypt(self, data, key, encodedKey=False, returnEncoded=True): '''Encrypt data to a 32-byte key (Salsa20-Poly1305 MAC)''' if encodedKey: diff --git a/onionr/onionrdaemontools.py b/onionr/onionrdaemontools.py index 8410cb80..c7b738e1 100644 --- a/onionr/onionrdaemontools.py +++ b/onionr/onionrdaemontools.py @@ -1,5 +1,5 @@ ''' - Onionr - P2P Microblogging Platform & Social network. + Onionr - P2P Anonymous Storage Network Contains the CommunicatorUtils class which contains useful functions for the communicator daemon ''' diff --git a/onionr/onionrexceptions.py b/onionr/onionrexceptions.py index b26a97d7..dbdab69a 100644 --- a/onionr/onionrexceptions.py +++ b/onionr/onionrexceptions.py @@ -1,5 +1,5 @@ ''' - Onionr - P2P Microblogging Platform & Social network. + Onionr - P2P Anonymous Storage Network This file contains exceptions for onionr ''' @@ -34,6 +34,9 @@ class OnlinePeerNeeded(Exception): class InvalidPubkey(Exception): pass +class KeyNotKnown(Exception): + pass + # block exceptions class InvalidMetadata(Exception): pass diff --git a/onionr/onionrpeers.py b/onionr/onionrpeers.py index 710f698d..6a34adf7 100644 --- a/onionr/onionrpeers.py +++ b/onionr/onionrpeers.py @@ -1,5 +1,5 @@ ''' - Onionr - P2P Microblogging Platform & Social network. + Onionr - P2P Anonymous Storage Network This file contains both the PeerProfiles class for network profiling of Onionr nodes ''' diff --git a/onionr/onionrusers.py b/onionr/onionrusers.py new file mode 100644 index 00000000..9138e1ce --- /dev/null +++ b/onionr/onionrusers.py @@ -0,0 +1,51 @@ +''' + Onionr - P2P Anonymous Storage Network + + Contains abstractions for interacting with users of Onionr +''' +''' + 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 . +''' +class OnionrUser: + def __init__(self, coreInst, publicKey): + self.trust = 0 + self._core = coreInst + self.publicKey = publicKey + + self.trust = self._core.getPeerInfo(self.publicKey, 'trust') + return + + def setTrust(self, newTrust): + '''Set the peers trust. 0 = not trusted, 1 = friend, 2 = ultimate''' + self._core.setPeerInfo(self.publicKey, 'trust', newTrust) + + def isFriend(self): + if self._core.getPeerInfo(self.publicKey, 6) == 1: + return True + return False + + def encrypt(self, data): + encrypted = coreInst._crypto.pubKeyEncrypt(data, self.publicKey, encodedData=True) + return encrypted + + def decrypt(self, data): + decrypted = coreInst._crypto.pubKeyDecrypt(data, self.publicKey, encodedData=True) + return decrypted + + def forwardEncrypt(self, data): + return + + def forwardDecrypt(self, encrypted): + return + \ No newline at end of file diff --git a/onionr/onionrutils.py b/onionr/onionrutils.py index 6d22992c..8e8f5ab8 100644 --- a/onionr/onionrutils.py +++ b/onionr/onionrutils.py @@ -264,9 +264,24 @@ class OnionrUtils: if myBlock.isEncrypted: myBlock.decrypt() blockType = myBlock.getMetadata('type') # we would use myBlock.getType() here, but it is bugged with encrypted blocks + signer = myBlock.getSigner() + try: if len(blockType) <= 10: self._core.updateBlockInfo(blockHash, 'dataType', blockType) + + if blockType == 'userInfo': + if myBlock.verifySig(): + peerName = myBlock.getMetadata('name') + try: + if len(peerName) > 20: + raise onionrexceptions.InvalidMetdata('Peer name specified is too large') + except TypeError: + pass + except onionrexceptions.InvalidMetadata: + pass + else: + self._core.setPeerInfo(signer, 'name', peerName) except TypeError: pass diff --git a/onionr/static-data/index.html b/onionr/static-data/index.html index 93e48beb..a48dad37 100644 --- a/onionr/static-data/index.html +++ b/onionr/static-data/index.html @@ -1,6 +1,6 @@

This is an Onionr Node

-

The content on this server is not necessarily created by the server owner, and was not necessarily stored with the owner's knowledge.

+

The content on this server is not necessarily created by the server owner, and was not necessarily stored specifically with the owner's knowledge of its contents.

Onionr is a decentralized, distributed data storage system, that anyone can insert data into.