diff --git a/api.py b/api.py
index 0edeabab..6e450e61 100755
--- a/api.py
+++ b/api.py
@@ -14,19 +14,27 @@
along with this program. If not, see .
'''
import flask
-from flask import request, Response
-import configparser, sys, random, threading
+from flask import request, Response, abort
+import configparser, sys, random, threading, hmac, hashlib, base64
+
+from core import Core
'''
Main API
'''
class API:
-
+ def validateToken(self, token):
+ if self.clientToken != token:
+ return False
+ else:
+ return True
+
def __init__(self, config, debug):
self.config = config
self.debug = debug
app = flask.Flask(__name__)
bindPort = int(self.config['CLIENT']['PORT'])
- clientToken = self.config['CLIENT']['CLIENT HMAC']
+ self.bindPort = bindPort
+ self.clientToken = self.config['CLIENT']['CLIENT HMAC']
if not debug:
hostNums = [random.randint(1, 255), random.randint(1, 255), random.randint(1, 255)]
@@ -47,20 +55,35 @@ class API:
resp.headers['x-frame-options'] = 'deny'
return resp
- @app.route('/client/hello')
- def hello_world():
+ @app.route('/client/')
+ def private_handler():
+ # we should keep a hash DB of requests (with hmac) to prevent replays
+ action = request.args.get('action')
+ #if not self.debug:
+ token = request.args.get('token')
+ if not self.validateToken(token):
+ abort(403)
self.validateHost()
- resp = Response('Hello, World!' + request.host)
+ if action == 'hello':
+ resp = Response('Hello, World! ' + request.host)
+ elif action == 'stats':
+ resp =Response('something')
+ else:
+ resp = Response('(O_o) Dude what? (invalid command)')
return resp
@app.errorhandler(404)
def notfound(err):
resp = Response("\_(0_0)_/ I got nothin")
- resp.headers = getHeaders(resp)
+ #resp.headers = getHeaders(resp)
+ return resp
+ @app.errorhandler(403)
+ def authFail(err):
+ resp = Response("Auth required/security failure")
return resp
print('Starting client on ' + self.host + ':' + str(bindPort))
- print('Client token:', clientToken)
+ print('Client token:', self.clientToken)
app.run(host=self.host, port=bindPort, debug=True, threaded=True)
@@ -68,10 +91,14 @@ class API:
if self.debug:
return
# Validate host header, to protect against DNS rebinding attacks
- if request.host != '127.0.0.1:' + str(self.config['CLIENT']['PORT']):
- sys.exit(1)
+ host = self.host
+ if not request.host.startswith('127'):
+ abort(403)
# Validate x-requested-with, to protect against CSRF/metadata leaks
+ '''
try:
request.headers['x-requested-with']
except:
+ # we exit rather than abort to avoid fingerprinting
sys.exit(1)
+ '''
\ No newline at end of file
diff --git a/core.py b/core.py
new file mode 100644
index 00000000..3d994403
--- /dev/null
+++ b/core.py
@@ -0,0 +1,47 @@
+'''
+ Onionr - P2P Microblogging Platform & Social network
+ 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, os, time, math
+class Core:
+ def __init__(self):
+ self.queueDB = 'data/queue.db'
+ self.daemonQueue() # Call to create the DB if it doesn't exist
+ return
+
+ def daemonQueue(self):
+ # Queue to exchange data between "client" and server.
+ retData = False
+ conn = sqlite3.connect(self.queueDB)
+ c = conn.cursor()
+ if not os.path.exists(self.queueDB):
+ # Create table
+ c.execute('''CREATE TABLE commands
+ (id integer primary key autoincrement, command text, data text, date text)''')
+ conn.commit()
+ else:
+ retData = c.execute('SELECT command, data, date, min(ID) FROM commands group by id')[0]
+ conn.close()
+
+ return retData
+
+ def daemonQueueAdd(self, command, data=''):
+ date = math.floor(time.time())
+ conn = sqlite3.connect(self.queueDB)
+ c = conn.cursor()
+ t = (command, data, date)
+ c.execute('INSERT into commands (command, data, date) values (?, ?, ?)', t)
+ conn.commit()
+ conn.close()
+ return
\ No newline at end of file
diff --git a/onionr.py b/onionr.py
index 82d7474b..e3174ac7 100755
--- a/onionr.py
+++ b/onionr.py
@@ -20,11 +20,12 @@ from colors import Colors
class Onionr:
def __init__(self):
+
colors = Colors()
# Get configuration and Handle commands
- self.debug = True # Whole application debugging
+ self.debug = False # Whole application debugging
os.chdir(sys.path[0])
diff --git a/tests.py b/tests.py
new file mode 100755
index 00000000..d24e5a9b
--- /dev/null
+++ b/tests.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python3
+'''
+ Onionr - P2P Microblogging Platform & Social network
+ 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 unittest, sys, os
+
+class OnionrTests(unittest.TestCase):
+ def testNone(self):
+ # Test just running ./onionr with no arguments
+ blank = os.system('./onionr.py')
+ if blank != 0:
+ self.assertTrue(False)
+ else:
+ self.assertTrue(True)
+
+unittest.main()
\ No newline at end of file