diff --git a/server.py b/server.py index e2ed9250c4cc73dc5d0c09e9638ff0852420190e..75d176788ff89a68859e6859b69952b7e4bb0b03 100644 --- a/server.py +++ b/server.py @@ -56,6 +56,7 @@ MIX_REQ_AGE_MAX = 604800 # maximum mix request age before return to sender PEER_INFO_INTERVAL = 600 # interval for renewing my peer document PEER_SIG_AGE_MAX = 604800 # max age of a peer document signature PEER_DETECT_INTERVAL = 120 # interval for fetching peer list +IDTY_SIG_AGE_MAX = 2592000 # max age of a idty document signature CURRENCY = "g1" def send_response(client, code, resp, dataformat="ubjson"): @@ -190,6 +191,7 @@ def read_config(cdir, conf_overwrite={}): conf["server"].setdefault("peer_info_interval", PEER_INFO_INTERVAL) conf["server"].setdefault("peer_sig_age_max", PEER_SIG_AGE_MAX) conf["server"].setdefault("peer_detect_interval", PEER_DETECT_INTERVAL) + conf["server"].setdefault("idty_sig_age_max", IDTY_SIG_AGE_MAX) conf.setdefault("client", {}) conf["client"].setdefault("bma_hosts", BMA_HOSTS) conf["client"].setdefault("proxy", None) @@ -985,6 +987,8 @@ if __name__ == "__main__": # Generate peer info local_peer = utils.Peer.generate(conf, keys) + if local_peer == None: + exit() peer_file = open(os.path.expanduser(utils.getargv("-e", "peer_info.ubjson")), "wb") peer_file.write(ubjson.dumpb([local_peer.raw])) diff --git a/utils.py b/utils.py index de4e5db1c71834430fe44b3bbb3c5854fb41276c..28b7deb0e00601d66fc833fde016e337b89a51cf 100644 --- a/utils.py +++ b/utils.py @@ -132,29 +132,62 @@ def run_async(coro): #-------- ÄžMixer +def verify_idty_sig(conf, raw, idty_pubkey, peer_pubkey): + try: + raw = libnacl.sign.Verifier(PublicKey(idty_pubkey).hex_pk()).verify(raw) + data = ubjson.loadb(raw) + assert data["doctype"] == "gmixer/idtysig" , "Bad doctype" + assert data["docver"] == "1" , "Bad docver" + assert data["pubkey"] == peer_pubkey , "Bad pubkey" + t = time.time() + assert data["sigtime"] < t and data["sigtime"] + conf["server"]["idty_sig_age_max"] > t , "Bad sigtime" + except (ValueError, IndexError, ubjson.decoder.DecoderException, AssertionError) as e: + logprint("Bad idty sig: "+str(e), LOG_TRACE) + return False + return True + class Peer: VERSION = "1" def __init__(self, conf:dict, raw:bytes): self.rectime = time.time() self.raw = raw - data = ubjson.loadb(raw) + try: + data = ubjson.loadb(raw) + except ubjson.decoder.DecoderException: + raise AssertionError("Bad wrapper encoding") + + assert "pubkey" in data and "raw" in data , "Missing values in wrapper" pubkey = data["pubkey"] - raw = libnacl.sign.Verifier(PublicKey(pubkey).hex_pk()).verify(data["raw"]) - data = ubjson.loadb(raw) - # TODO try except + try: + raw = libnacl.sign.Verifier(PublicKey(pubkey).hex_pk()).verify(data["raw"]) + except ValueError: + raise AssertionError("Bad signature") + try: + data = ubjson.loadb(raw) + except ubjson.decoder.DecoderException: + raise AssertionError("Bad data encoding") + + assert "doctype" in data and "docver" in data and "currency" in data and "pubkey" in data and "sigtime" in data and "host" in data and "idty" in data and "idtysig" in data ,\ + "Missing values in data" + + assert data["doctype"] == "gmixer/peer" , "Bad doctype" + assert data["docver"] == Peer.VERSION , "Bad docver" + assert data["currency"] == conf["currency"] , "Different currency" + assert data["pubkey"] == pubkey , "Different pubkey" + assert isinstance(data["sigtime"], (int, float)) , "Bad sigtime" + assert data["sigtime"] < self.rectime , "Futuristic sigtime" - # TODO tests - assert data["currency"] == conf["currency"] , "Not the same currency" if conf["idty"]["needed"]: - assert run_async(check_idty(conf["client"]["bma_hosts"], data["idty"])) + assert run_async(check_idty(conf["client"]["bma_hosts"], data["idty"])) , "Idty is not member" + assert verify_idty_sig(conf, data["idtysig"], data["idty"], pubkey) , "Bad idty sig" self.doctype = data["doctype"] self.docver = data["docver"] self.pubkey = data["pubkey"] - self.sigtime = data["sigtime"] + self.sigtime = data["sigtime"] self.host = tuple(data["host"]) # socket cannot manage lists self.idty = data["idty"] - self.idtysig = data["idtysig"] + self.idtysig = data["idtysig"]# TODO check self.hash = hashlib.sha512((self.pubkey+"@"+self.host[0]+":"+str(self.host[1])).encode()).digest() self.keys = PublicKey(self.pubkey) @@ -165,7 +198,7 @@ class Peer: def generate(conf:dict, keys:SigningKey) -> bytes: data = { - "doctype": "peer", + "doctype": "gmixer/peer", "docver": Peer.VERSION, "currency": conf["currency"], "pubkey": keys.pubkey, @@ -182,7 +215,8 @@ class Peer: raw = ubjson.dumpb(data) try: return Peer(conf, raw) - except AssertionError: + except AssertionError as e: + logprint("Gen peer: "+str(e), LOG_ERROR) return None def load_peers(conf:dict, db_peers:plyvel.DB, peers:dict): @@ -207,9 +241,6 @@ async def bma_client(bma_endpoints:list): client = None return client -#async def check_idty(client:Client, pubkey:str): -# print( await client(bma.wot.lookup, pubkey)) - async def check_idty(bma_endpoints:list, pubkey:str): client = await bma_client(bma_endpoints) try: