parent
9571ea519d
commit
1019ff0773
|
@ -1,4 +1,4 @@
|
||||||
"""Flask WSGI apps for the public and private API servers
|
"""Flask WSGI apps for the public and private API servers.
|
||||||
|
|
||||||
Public is net-facing server meant for other nodes
|
Public is net-facing server meant for other nodes
|
||||||
Private is meant for controlling and accessing this node
|
Private is meant for controlling and accessing this node
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
'''
|
"""Onionr - Private P2P Communication.
|
||||||
Onionr - Private P2P Communication
|
|
||||||
|
|
||||||
This file handles all incoming http requests to the client, using Flask
|
This file handles all incoming http requests to the client, using Flask
|
||||||
'''
|
"""
|
||||||
import base64
|
from typing import Dict
|
||||||
import os
|
import hmac
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
from gevent.pywsgi import WSGIServer
|
from gevent.pywsgi import WSGIServer
|
||||||
|
@ -18,7 +17,7 @@ from etc import waitforsetvar
|
||||||
from . import register_private_blueprints
|
from . import register_private_blueprints
|
||||||
import config
|
import config
|
||||||
from .. import public
|
from .. import public
|
||||||
'''
|
"""
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
@ -31,24 +30,22 @@ from .. import public
|
||||||
|
|
||||||
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/>.
|
||||||
'''
|
"""
|
||||||
|
|
||||||
|
|
||||||
class PrivateAPI:
|
class PrivateAPI:
|
||||||
'''
|
"""Client HTTP api for controlling onionr and using UI."""
|
||||||
Client HTTP api
|
|
||||||
'''
|
|
||||||
|
|
||||||
callbacks = {'public': {}, 'private': {}}
|
callbacks: Dict[str, Dict] = {'public': {}, 'private': {}}
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
'''
|
"""Initialize the api server, preping variables for later use.
|
||||||
Initialize the api server, preping variables for later use
|
|
||||||
|
|
||||||
This initialization defines all of the API entry points
|
This initialization defines all of the API entry points
|
||||||
and handlers for the endpoints and errors
|
and handlers for the endpoints and errors
|
||||||
This also saves the used host (random localhost IP address) to the data folder in host.txt
|
This also saves the used host (random localhost IP address)
|
||||||
'''
|
to the data folder in host.txt
|
||||||
|
"""
|
||||||
self.config = config
|
self.config = config
|
||||||
|
|
||||||
self.startTime = epoch.get_epoch()
|
self.startTime = epoch.get_epoch()
|
||||||
|
@ -58,7 +55,8 @@ class PrivateAPI:
|
||||||
|
|
||||||
self.clientToken = config.get('client.webpassword')
|
self.clientToken = config.get('client.webpassword')
|
||||||
|
|
||||||
self.host = httpapi.apiutils.setbindip.set_bind_IP(private_API_host_file)
|
self.host = httpapi.apiutils.setbindip.set_bind_IP(
|
||||||
|
private_API_host_file)
|
||||||
logger.info('Running api on %s:%s' % (self.host, self.bindPort))
|
logger.info('Running api on %s:%s' % (self.host, self.bindPort))
|
||||||
self.httpServer = ''
|
self.httpServer = ''
|
||||||
|
|
||||||
|
@ -69,18 +67,25 @@ class PrivateAPI:
|
||||||
self.app = app
|
self.app = app
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
|
"""Start client gevent API web server with flask client app."""
|
||||||
waitforsetvar.wait_for_set_var(self, "_too_many")
|
waitforsetvar.wait_for_set_var(self, "_too_many")
|
||||||
self.publicAPI = self._too_many.get(public.PublicAPI)
|
fd_handler = httpapi.fdsafehandler.FDSafeHandler
|
||||||
self.httpServer = WSGIServer((self.host, self.bindPort), self.app, log=None, handler_class=httpapi.fdsafehandler.FDSafeHandler)
|
self.publicAPI = self._too_many.get( # pylint: disable=E1101
|
||||||
|
public.PublicAPI)
|
||||||
|
self.httpServer = WSGIServer((self.host, self.bindPort),
|
||||||
|
self.app, log=None,
|
||||||
|
handler_class=fd_handler)
|
||||||
self.httpServer.serve_forever()
|
self.httpServer.serve_forever()
|
||||||
|
|
||||||
def setPublicAPIInstance(self, inst):
|
def setPublicAPIInstance(self, inst):
|
||||||
|
"""Dynamically set public API instance."""
|
||||||
self.publicAPI = inst
|
self.publicAPI = inst
|
||||||
|
|
||||||
def validateToken(self, token):
|
def validateToken(self, token):
|
||||||
'''
|
"""Validate that the client token matches the given token.
|
||||||
Validate that the client token matches the given token. Used to prevent CSRF and data exfiltration
|
|
||||||
'''
|
Used to prevent CSRF and other attacks.
|
||||||
|
"""
|
||||||
if not self.clientToken:
|
if not self.clientToken:
|
||||||
logger.error("client password needs to be set")
|
logger.error("client password needs to be set")
|
||||||
return False
|
return False
|
||||||
|
@ -89,7 +94,8 @@ class PrivateAPI:
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def getUptime(self)->int:
|
def getUptime(self) -> int:
|
||||||
|
"""Safely wait for uptime to be set and return it."""
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
return epoch.get_epoch() - self.startTime
|
return epoch.get_epoch() - self.startTime
|
||||||
|
@ -97,5 +103,10 @@ class PrivateAPI:
|
||||||
# Don't error on race condition with startup
|
# Don't error on race condition with startup
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def getBlockData(self, bHash, decrypt=False, raw=False, headerOnly=False):
|
def getBlockData(self, bHash, decrypt=False, raw=False,
|
||||||
return self.get_block_data.get_block_data(bHash, decrypt=decrypt, raw=raw, headerOnly=headerOnly)
|
headerOnly=False) -> bytes:
|
||||||
|
"""Returns block data bytes."""
|
||||||
|
return self.get_block_data.get_block_data(bHash,
|
||||||
|
decrypt=decrypt,
|
||||||
|
raw=raw,
|
||||||
|
headerOnly=headerOnly)
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
'''
|
"""Onionr - Private P2P Communication.
|
||||||
Onionr - Private P2P Communication
|
|
||||||
|
|
||||||
This file registers blueprints for the private api server
|
This file registers blueprints for the private api server
|
||||||
'''
|
"""
|
||||||
'''
|
from httpapi import security, friendsapi, profilesapi, configapi, insertblock
|
||||||
|
from httpapi import miscclientapi, onionrsitesapi, apiutils
|
||||||
|
from httpapi import directconnections
|
||||||
|
from httpapi import themeapi
|
||||||
|
"""
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
@ -16,24 +19,25 @@
|
||||||
|
|
||||||
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 os
|
|
||||||
from httpapi import security, friendsapi, profilesapi, configapi, insertblock, miscclientapi, onionrsitesapi, apiutils
|
|
||||||
from httpapi import directconnections
|
|
||||||
from httpapi import themeapi
|
|
||||||
|
|
||||||
def register_private_blueprints(private_api, app):
|
def register_private_blueprints(private_api, app):
|
||||||
app.register_blueprint(security.client.ClientAPISecurity(private_api).client_api_security_bp)
|
"""Register private API plask blueprints."""
|
||||||
|
app.register_blueprint(security.client.ClientAPISecurity(
|
||||||
|
private_api).client_api_security_bp)
|
||||||
app.register_blueprint(friendsapi.friends)
|
app.register_blueprint(friendsapi.friends)
|
||||||
app.register_blueprint(profilesapi.profile_BP)
|
app.register_blueprint(profilesapi.profile_BP)
|
||||||
app.register_blueprint(configapi.config_BP)
|
app.register_blueprint(configapi.config_BP)
|
||||||
app.register_blueprint(insertblock.ib)
|
app.register_blueprint(insertblock.ib)
|
||||||
app.register_blueprint(miscclientapi.getblocks.client_get_blocks)
|
app.register_blueprint(miscclientapi.getblocks.client_get_blocks)
|
||||||
app.register_blueprint(miscclientapi.endpoints.PrivateEndpoints(private_api).private_endpoints_bp)
|
app.register_blueprint(miscclientapi.endpoints.PrivateEndpoints(
|
||||||
|
private_api).private_endpoints_bp)
|
||||||
app.register_blueprint(miscclientapi.motd.bp)
|
app.register_blueprint(miscclientapi.motd.bp)
|
||||||
app.register_blueprint(onionrsitesapi.site_api)
|
app.register_blueprint(onionrsitesapi.site_api)
|
||||||
app.register_blueprint(apiutils.shutdown.shutdown_bp)
|
app.register_blueprint(apiutils.shutdown.shutdown_bp)
|
||||||
app.register_blueprint(miscclientapi.staticfiles.static_files_bp)
|
app.register_blueprint(miscclientapi.staticfiles.static_files_bp)
|
||||||
app.register_blueprint(directconnections.DirectConnectionManagement(private_api).direct_conn_management_bp)
|
app.register_blueprint(directconnections.DirectConnectionManagement(
|
||||||
|
private_api).direct_conn_management_bp)
|
||||||
app.register_blueprint(themeapi.theme_blueprint)
|
app.register_blueprint(themeapi.theme_blueprint)
|
||||||
return app
|
return app
|
||||||
|
|
|
@ -1,9 +1,19 @@
|
||||||
'''
|
"""Onionr - Private P2P Communication.
|
||||||
Onionr - Private P2P Communication
|
|
||||||
|
|
||||||
This file handles all incoming http requests to the public api server, using Flask
|
This file handles all incoming http requests
|
||||||
'''
|
to the public api server, using Flask
|
||||||
'''
|
"""
|
||||||
|
import time
|
||||||
|
import threading
|
||||||
|
import flask
|
||||||
|
from gevent.pywsgi import WSGIServer
|
||||||
|
from httpapi import apiutils, security, fdsafehandler, miscpublicapi
|
||||||
|
import logger
|
||||||
|
import config
|
||||||
|
import filepaths
|
||||||
|
from utils import gettransports
|
||||||
|
from etc import onionrvalues, waitforsetvar
|
||||||
|
"""
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
@ -16,15 +26,8 @@
|
||||||
|
|
||||||
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 time
|
|
||||||
import threading
|
|
||||||
import flask
|
|
||||||
from gevent.pywsgi import WSGIServer
|
|
||||||
from httpapi import apiutils, security, fdsafehandler, miscpublicapi
|
|
||||||
import logger, config, filepaths
|
|
||||||
from utils import gettransports
|
|
||||||
from etc import onionrvalues, waitforsetvar
|
|
||||||
|
|
||||||
def _get_tor_adder(pub_api):
|
def _get_tor_adder(pub_api):
|
||||||
transports = []
|
transports = []
|
||||||
|
@ -33,32 +36,41 @@ def _get_tor_adder(pub_api):
|
||||||
time.sleep(0.3)
|
time.sleep(0.3)
|
||||||
pub_api.torAdder = transports[0]
|
pub_api.torAdder = transports[0]
|
||||||
|
|
||||||
|
|
||||||
class PublicAPI:
|
class PublicAPI:
|
||||||
'''
|
"""The new client api server, isolated from the public api."""
|
||||||
The new client api server, isolated from the public api
|
|
||||||
'''
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
"""Setup the public api app."""
|
||||||
app = flask.Flask('PublicAPI')
|
app = flask.Flask('PublicAPI')
|
||||||
app.config['MAX_CONTENT_LENGTH'] = 5 * 1024 * 1024
|
app.config['MAX_CONTENT_LENGTH'] = 5 * 1024 * 1024
|
||||||
self.i2pEnabled = config.get('i2p.host', False)
|
self.i2pEnabled = config.get('i2p.host', False)
|
||||||
self.hideBlocks = [] # Blocks to be denied sharing
|
self.hideBlocks = [] # Blocks to be denied sharing
|
||||||
self.host = apiutils.setbindip.set_bind_IP(filepaths.public_API_host_file)
|
self.host = apiutils.setbindip.set_bind_IP(
|
||||||
|
filepaths.public_API_host_file)
|
||||||
|
|
||||||
threading.Thread(target=_get_tor_adder, args=[self], daemon=True).start()
|
threading.Thread(target=_get_tor_adder,
|
||||||
|
args=[self], daemon=True).start()
|
||||||
|
|
||||||
self.torAdder = ""
|
self.torAdder = ""
|
||||||
self.bindPort = config.get('client.public.port')
|
self.bindPort = config.get('client.public.port')
|
||||||
self.lastRequest = 0
|
self.lastRequest = 0
|
||||||
self.hitCount = 0 # total rec requests to public api since server started
|
# total rec requests to public api since server started
|
||||||
|
self.hitCount = 0
|
||||||
self.config = config
|
self.config = config
|
||||||
self.API_VERSION = onionrvalues.API_VERSION
|
self.API_VERSION = onionrvalues.API_VERSION
|
||||||
logger.info('Running public api on %s:%s' % (self.host, self.bindPort))
|
logger.info('Running public api on %s:%s' % (self.host, self.bindPort))
|
||||||
|
|
||||||
app.register_blueprint(security.public.PublicAPISecurity(self).public_api_security_bp)
|
app.register_blueprint(
|
||||||
app.register_blueprint(miscpublicapi.endpoints.PublicEndpoints(self).public_endpoints_bp)
|
security.public.PublicAPISecurity(self).public_api_security_bp)
|
||||||
|
app.register_blueprint(
|
||||||
|
miscpublicapi.endpoints.PublicEndpoints(self).public_endpoints_bp)
|
||||||
self.app = app
|
self.app = app
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
|
"""Start the Public API server."""
|
||||||
waitforsetvar.wait_for_set_var(self, "_too_many")
|
waitforsetvar.wait_for_set_var(self, "_too_many")
|
||||||
self.httpServer = WSGIServer((self.host, self.bindPort), self.app, log=None, handler_class=fdsafehandler.FDSafeHandler)
|
self.httpServer = WSGIServer((self.host, self.bindPort),
|
||||||
self.httpServer.serve_forever()
|
self.app, log=None,
|
||||||
|
handler_class=fdsafehandler.FDSafeHandler)
|
||||||
|
self.httpServer.serve_forever()
|
||||||
|
|
|
@ -54,7 +54,7 @@ def get_online_peers(comm_inst: 'OnionrCommunicatorDaemon'):
|
||||||
else:
|
else:
|
||||||
if len(comm_inst.onlinePeers) == 0:
|
if len(comm_inst.onlinePeers) == 0:
|
||||||
logger.debug('Couldn\'t connect to any peers.' +
|
logger.debug('Couldn\'t connect to any peers.' +
|
||||||
f' Last node seen {last_seen} ago.')
|
f' Last node seen {last_seen} ago.')
|
||||||
else:
|
else:
|
||||||
comm_inst.lastNodeSeen = time.time()
|
comm_inst.lastNodeSeen = time.time()
|
||||||
comm_inst.decrementThreadCount('get_online_peers')
|
comm_inst.decrementThreadCount('get_online_peers')
|
||||||
|
|
|
@ -34,10 +34,10 @@ def pick_online_peer(comm_inst):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Get a random online peer, securely.
|
# Get a random online peer, securely.
|
||||||
# May get stuck in loop if network is lost or if all peers in pool magically disconnect at once
|
# May get stuck in loop if network is lost
|
||||||
ret_data = comm_inst.onlinePeers[secrets.randbelow(peer_length)]
|
ret_data = comm_inst.onlinePeers[secrets.randbelow(peer_length)]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
return ret_data
|
return ret_data
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
'''
|
"""Onionr - Private P2P Communication.
|
||||||
Onionr - Private P2P Communication
|
|
||||||
|
|
||||||
remove an online peer from the pool in a communicator instance
|
remove an online peer from the pool in a communicator instance
|
||||||
'''
|
"""
|
||||||
'''
|
"""
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
@ -16,9 +15,11 @@
|
||||||
|
|
||||||
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/>.
|
||||||
'''
|
"""
|
||||||
|
|
||||||
|
|
||||||
def remove_online_peer(comm_inst, peer):
|
def remove_online_peer(comm_inst, peer):
|
||||||
'''Remove an online peer'''
|
"""Remove an online peer."""
|
||||||
try:
|
try:
|
||||||
del comm_inst.connectTimes[peer]
|
del comm_inst.connectTimes[peer]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
@ -30,4 +31,4 @@ def remove_online_peer(comm_inst, peer):
|
||||||
try:
|
try:
|
||||||
comm_inst.onlinePeers.remove(peer)
|
comm_inst.onlinePeers.remove(peer)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
Loading…
Reference in New Issue