timing attack identity correlation prevention added, python3 test, more fingerprinting prevention, began work on PGP core
This commit is contained in:
		
							parent
							
								
									fb0309a414
								
							
						
					
					
						commit
						2898dbaafa
					
				
					 6 changed files with 60 additions and 12 deletions
				
			
		
							
								
								
									
										4
									
								
								LICENSE
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								LICENSE
									
										
									
									
									
								
							|  | @ -1,3 +1,7 @@ | ||||||
|  | Onionr Logo is licensed under Creative Commons Attribution-Share Alike 3.0 Unported | ||||||
|  | https://creativecommons.org/licenses/by-sa/4.0/ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|                     GNU GENERAL PUBLIC LICENSE |                     GNU GENERAL PUBLIC LICENSE | ||||||
|                        Version 3, 29 June 2007 |                        Version 3, 29 June 2007 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										39
									
								
								api.py
									
										
									
									
									
								
							
							
						
						
									
										39
									
								
								api.py
									
										
									
									
									
								
							|  | @ -15,7 +15,7 @@ | ||||||
| ''' | ''' | ||||||
| import flask | import flask | ||||||
| from flask import request, Response, abort | from flask import request, Response, abort | ||||||
| import configparser, sys, random, threading, hmac, hashlib, base64 | import configparser, sys, random, threading, hmac, hashlib, base64, time, math, gnupg | ||||||
| 
 | 
 | ||||||
| from core import Core | from core import Core | ||||||
| ''' | ''' | ||||||
|  | @ -31,6 +31,8 @@ class API: | ||||||
|     def __init__(self, config, debug): |     def __init__(self, config, debug): | ||||||
|         self.config = config |         self.config = config | ||||||
|         self.debug = debug |         self.debug = debug | ||||||
|  |         self._privateDelayTime = 3 | ||||||
|  |         self._core = Core() | ||||||
|         app = flask.Flask(__name__) |         app = flask.Flask(__name__) | ||||||
|         bindPort = int(self.config['CLIENT']['PORT']) |         bindPort = int(self.config['CLIENT']['PORT']) | ||||||
|         self.bindPort = bindPort |         self.bindPort = bindPort | ||||||
|  | @ -44,11 +46,14 @@ class API: | ||||||
| 
 | 
 | ||||||
|         @app.before_request |         @app.before_request | ||||||
|         def beforeReq(): |         def beforeReq(): | ||||||
|  |             self.requestFailed = False | ||||||
|             return |             return | ||||||
| 
 | 
 | ||||||
|         @app.after_request |         @app.after_request | ||||||
|         def afterReq(resp): |         def afterReq(resp): | ||||||
|  |             if not self.requestFailed: | ||||||
|                 resp.headers['Access-Control-Allow-Origin'] = '*' |                 resp.headers['Access-Control-Allow-Origin'] = '*' | ||||||
|  |             else: | ||||||
|                 resp.headers['server'] = 'Onionr' |                 resp.headers['server'] = 'Onionr' | ||||||
|             resp.headers['content-type'] = 'text/plain' |             resp.headers['content-type'] = 'text/plain' | ||||||
|             resp.headers["Content-Security-Policy"] = "default-src 'none'" |             resp.headers["Content-Security-Policy"] = "default-src 'none'" | ||||||
|  | @ -57,29 +62,47 @@ class API: | ||||||
|              |              | ||||||
|         @app.route('/client/') |         @app.route('/client/') | ||||||
|         def private_handler(): |         def private_handler(): | ||||||
|  |             startTime = math.floor(time.time()) | ||||||
|             # we should keep a hash DB of requests (with hmac) to prevent replays |             # we should keep a hash DB of requests (with hmac) to prevent replays | ||||||
|             action = request.args.get('action') |             action = request.args.get('action') | ||||||
|             #if not self.debug: |             #if not self.debug: | ||||||
|             token = request.args.get('token') |             token = request.args.get('token') | ||||||
|             if not self.validateToken(token): |             if not self.validateToken(token): | ||||||
|                 abort(403) |                 abort(403) | ||||||
|             self.validateHost() |             self.validateHost('private') | ||||||
|             if action == 'hello': |             if action == 'hello': | ||||||
|                 resp = Response('Hello, World! ' + request.host) |                 resp = Response('Hello, World! ' + request.host) | ||||||
|             elif action == 'stats': |             elif action == 'stats': | ||||||
|                 resp =Response('something') |                 resp = Response('something') | ||||||
|  |             elif action == 'init': | ||||||
|  |                 # generate PGP key | ||||||
|  |                 pass | ||||||
|  | 
 | ||||||
|             else: |             else: | ||||||
|                 resp = Response('(O_o) Dude what? (invalid command)') |                 resp = Response('(O_o) Dude what? (invalid command)') | ||||||
|  |             endTime = math.floor(time.time()) | ||||||
|  |             elapsed = endTime - startTime | ||||||
|  |             if elapsed < self._privateDelayTime: | ||||||
|  |                 time.sleep(self._privateDelayTime - elapsed) | ||||||
|             return resp |             return resp | ||||||
| 
 | 
 | ||||||
|  |         @app.route('/public/') | ||||||
|  |         def public_handler(): | ||||||
|  |             # Public means it is publicly network accessible | ||||||
|  |             self.validateHost('public') | ||||||
|  |             action = request.args.get('action') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|         @app.errorhandler(404) |         @app.errorhandler(404) | ||||||
|         def notfound(err): |         def notfound(err): | ||||||
|             resp = Response("\_(0_0)_/ I got nothin") |             self.requestFailed = True | ||||||
|  |             resp = Response("") | ||||||
|             #resp.headers = getHeaders(resp) |             #resp.headers = getHeaders(resp) | ||||||
|             return resp |             return resp | ||||||
|         @app.errorhandler(403) |         @app.errorhandler(403) | ||||||
|         def authFail(err): |         def authFail(err): | ||||||
|             resp = Response("Auth required/security failure") |             self.requestFailed = True | ||||||
|  |             resp = Response("403") | ||||||
|             return resp |             return resp | ||||||
| 
 | 
 | ||||||
|         print('Starting client on ' + self.host + ':' + str(bindPort)) |         print('Starting client on ' + self.host + ':' + str(bindPort)) | ||||||
|  | @ -87,13 +110,17 @@ class API: | ||||||
| 
 | 
 | ||||||
|         app.run(host=self.host, port=bindPort, debug=True, threaded=True) |         app.run(host=self.host, port=bindPort, debug=True, threaded=True) | ||||||
|      |      | ||||||
|     def validateHost(self): |     def validateHost(self, hostType): | ||||||
|         if self.debug: |         if self.debug: | ||||||
|             return |             return | ||||||
|         # Validate host header, to protect against DNS rebinding attacks |         # Validate host header, to protect against DNS rebinding attacks | ||||||
|         host = self.host |         host = self.host | ||||||
|  |         if hostType == 'private': | ||||||
|             if not request.host.startswith('127'): |             if not request.host.startswith('127'): | ||||||
|                 abort(403) |                 abort(403) | ||||||
|  |         elif hostType == 'public': | ||||||
|  |             if not request.host.endswith('onion') and not request.hosst.endswith('i2p'): | ||||||
|  |                 abort(403) | ||||||
|         # Validate x-requested-with, to protect against CSRF/metadata leaks |         # Validate x-requested-with, to protect against CSRF/metadata leaks | ||||||
|         ''' |         ''' | ||||||
|         try: |         try: | ||||||
|  |  | ||||||
							
								
								
									
										7
									
								
								core.py
									
										
									
									
									
								
							
							
						
						
									
										7
									
								
								core.py
									
										
									
									
									
								
							|  | @ -13,13 +13,18 @@ | ||||||
|     You should have received a copy of the GNU General Public License |     You should have received a copy of the GNU General Public License | ||||||
|     along with this program.  If not, see <https://www.gnu.org/licenses/>. |     along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||||
| ''' | ''' | ||||||
| import sqlite3, os, time, math | import sqlite3, os, time, math, gnupg | ||||||
| class Core: | class Core: | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         self.queueDB = 'data/queue.db' |         self.queueDB = 'data/queue.db' | ||||||
|         #self.daemonQueue() # Call to create the DB if it doesn't exist |         #self.daemonQueue() # Call to create the DB if it doesn't exist | ||||||
|         return |         return | ||||||
| 
 | 
 | ||||||
|  |     def generateMainPGP(self): | ||||||
|  |         # Generate main pgp key | ||||||
|  |         gpg = gnupg.GPG(gnupghome='data/pgp/') | ||||||
|  |         return | ||||||
|  | 
 | ||||||
|     def daemonQueue(self): |     def daemonQueue(self): | ||||||
|         # This function intended to be used by the client |         # This function intended to be used by the client | ||||||
|         # Queue to exchange data between "client" and server. |         # Queue to exchange data between "client" and server. | ||||||
|  |  | ||||||
|  | @ -43,7 +43,7 @@ class Onionr: | ||||||
|                 randomPort = 8080 |                 randomPort = 8080 | ||||||
|             else: |             else: | ||||||
|                 randomPort = random.randint(1024, 65535) |                 randomPort = random.randint(1024, 65535) | ||||||
|             self.config['CLIENT'] = {'CLIENT HMAC': base64.b64encode(os.urandom(32)).decode('utf-8'), 'PORT': randomPort} |             self.config['CLIENT'] = {'CLIENT HMAC': base64.b64encode(os.urandom(32)).decode('utf-8'), 'PORT': randomPort, 'API VERSION': '0.0.0'} | ||||||
|             with open('data/config.ini', 'w') as configfile: |             with open('data/config.ini', 'w') as configfile: | ||||||
|                 self.config.write(configfile) |                 self.config.write(configfile) | ||||||
|         command = '' |         command = '' | ||||||
|  | @ -67,6 +67,8 @@ class Onionr: | ||||||
|                 return |                 return | ||||||
|         return |         return | ||||||
|     def daemon(self): |     def daemon(self): | ||||||
|  |         os.system('./communicator.py') | ||||||
|  |         print('Started communicator') | ||||||
|         api.API(self.config, self.debug) |         api.API(self.config, self.debug) | ||||||
|         return |         return | ||||||
|     def killDaemon(self): |     def killDaemon(self): | ||||||
|  |  | ||||||
|  | @ -3,3 +3,7 @@ | ||||||
| P2P microblogging platform and social network, using Tor & I2P. | P2P microblogging platform and social network, using Tor & I2P. | ||||||
| 
 | 
 | ||||||
| Major work in progress. *NOT USABLE OR SAFE YET* | Major work in progress. *NOT USABLE OR SAFE YET* | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Development | ||||||
|  | 
 | ||||||
|  |  | ||||||
							
								
								
									
										6
									
								
								tests.py
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								tests.py
									
										
									
									
									
								
							|  | @ -17,6 +17,12 @@ | ||||||
| import unittest, sys, os | import unittest, sys, os | ||||||
| 
 | 
 | ||||||
| class OnionrTests(unittest.TestCase): | class OnionrTests(unittest.TestCase): | ||||||
|  |     def testPython3(self): | ||||||
|  |         if sys.version_info.major != 3: | ||||||
|  |             print(sys.version_info.major) | ||||||
|  |             self.assertTrue(False) | ||||||
|  |         else: | ||||||
|  |             self.assertTrue(True) | ||||||
|     def testNone(self): |     def testNone(self): | ||||||
|         print('--------------------------') |         print('--------------------------') | ||||||
|         print('Running simple program run test') |         print('Running simple program run test') | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue