diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..d9c2d33e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +data/config.ini +data/*.db diff --git a/api.py b/api.py index 6c008a9d..cef6c593 100755 --- a/api.py +++ b/api.py @@ -13,9 +13,41 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . ''' -from flask import Flask +from flask import Flask, request app = Flask(__name__) - +import configparser, sys, random +''' +Main API +''' class API: - def __init__(self): - return \ No newline at end of file + + def __init__(self, config, debug): + self.config = config + bindPort = int(self.config['CLIENT']['PORT']) + clientToken = self.config['CLIENT']['CLIENT HMAC'] + + if not debug: + hostNums = [random.randint(1, 255), random.randint(1, 255), random.randint(1, 255)] + self.host = '127.' + str(hostNums[0]) + '.' + str(hostNums[1]) + '.' + str(hostNums[2]) + else: + self.host = '127.0.0.1' + + @app.route('/client/hello') + def hello_world(): + self.validateHost() + return 'Hello, World!' + request.host + + print('Starting client on ' + self.host + ':' + str(bindPort)) + print('Client token:', clientToken) + + app.run(host=self.host, port=bindPort, debug=True) + + def validateHost(self): + # Validate host header, to protect against DNS rebinding attacks + if request.host != '127.0.0.1:' + str(self.config['CLIENT']['PORT']): + sys.exit(1) + # Validate x-requested-with, to protect against CSRF/metadata leaks + try: + request.headers['x-requested-with'] + except: + sys.exit(1) \ No newline at end of file diff --git a/onionr.py b/onionr.py index d5331aa6..a9f43fa4 100755 --- a/onionr.py +++ b/onionr.py @@ -14,9 +14,26 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . ''' -import sys, api, gui +import sys, os, threading, configparser, base64, random +import gui, api class Onionr: def __init__(self): + + self.debug = True # Whole application debugging + + os.chdir(sys.path[0]) + self.config = configparser.ConfigParser() + if os.path.exists('data/config.ini'): + self.config.read('data/config.ini') + else: + # Hostname should only be set if different from 127.x.x.x. Important for DNS rebinding attack prevention. + if debug: + randomPort = 8080 + else: + randomPort = random.randint(1024, 65535) + self.config['CLIENT'] = {'CLIENT HMAC': base64.b64encode(os.urandom(32)).decode('utf-8'), 'PORT': randomPort} + with open('data/config.ini', 'w') as configfile: + self.config.write(configfile) command = '' try: command = sys.argv[1].lower() @@ -32,9 +49,10 @@ class Onionr: elif command == 'help' or command == '--help': self.showHelp() else: - help(Onionr) + return return def daemon(self): + api.API(self.config, self.debug) return def killDaemon(self): return @@ -43,4 +61,4 @@ class Onionr: def showHelp(self): return -main = Onionr() \ No newline at end of file +Onionr() \ No newline at end of file