diff --git a/owrx/controllers/__init__.py b/owrx/controllers/__init__.py index 6839741..c00eebd 100644 --- a/owrx/controllers/__init__.py +++ b/owrx/controllers/__init__.py @@ -18,11 +18,7 @@ class Controller(object): if max_age is not None: headers["Cache-Control"] = "max-age: {0}".format(max_age) for key, value in headers.items(): - if isinstance(value, list): - for v in value: - self.handler.send_header(key, v) - else: - self.handler.send_header(key, value) + self.handler.send_header(key, value) self.handler.end_headers() if type(content) == str: content = content.encode() diff --git a/owrx/controllers/receiverid.py b/owrx/controllers/receiverid.py index 6489340..667c6be 100644 --- a/owrx/controllers/receiverid.py +++ b/owrx/controllers/receiverid.py @@ -6,16 +6,17 @@ from datetime import datetime class ReceiverIdController(Controller): def __init__(self, handler, request, options): super().__init__(handler, request, options) - self.authHeaders = [] + self.authHeader = None def send_response(self, content, code=200, content_type="text/html", last_modified: datetime = None, max_age=None, headers=None): - if headers is None: - headers = {} - headers['Authorization'] = self.authHeaders + if self.authHeader is not None: + if headers is None: + headers = {} + headers['Authorization'] = self.authHeader super().send_response(content, code=code, content_type=content_type, last_modified=last_modified, max_age=max_age, headers=headers) pass def handle_request(self): - headers = self.request.headers.get_all("Authorization", []) - self.authHeaders = [ReceiverId.getResponseHeader(h) for h in headers] + if "Authorization" in self.request.headers: + self.authHeader = ReceiverId.getResponseHeader(self.request.headers['Authorization']) super().handle_request() diff --git a/owrx/receiverid.py b/owrx/receiverid.py index 33c62f0..847bb34 100644 --- a/owrx/receiverid.py +++ b/owrx/receiverid.py @@ -2,7 +2,7 @@ import re import logging import hashlib import hmac -from datetime import datetime +from datetime import datetime, timezone from owrx.config import Config logger = logging.getLogger(__name__) @@ -38,18 +38,18 @@ class KeyChallenge(object): class KeyResponse(object): - def __init__(self, source, id, time: datetime, signature): + def __init__(self, source, id, time, signature): self.source = source self.id = id self.time = time self.signature = signature def __str__(self): - return "Time={time}, Response={source}-{id}-{signature}".format( + return "{source}-{id}-{time}-{signature}".format( source=self.source, id=self.id, + time=self.time, signature=self.signature, - time=self.time ) @@ -59,11 +59,16 @@ class ReceiverId(object): matches = headerRegex.match(requestHeader) if not matches: raise KeyException("invalid authorization header") - challenge = KeyChallenge(matches.group(1)) - key = ReceiverId.findKey(challenge) - if key is None: - return {} - return ReceiverId.signChallenge(challenge, key) + challenges = [KeyChallenge(i) for i in matches.group(1).split(",")] + + def signChallenge(challenge): + key = ReceiverId.findKey(challenge) + if key is None: + return + return ReceiverId.signChallenge(challenge, key) + + responses = [signChallenge(c) for c in challenges] + return ",".join(str(r) for r in responses if r is not None) @staticmethod def findKey(challenge): @@ -81,8 +86,9 @@ class ReceiverId(object): @staticmethod def signChallenge(challenge, key): - now = datetime.utcnow().isoformat() + now = datetime.utcnow().replace(microsecond=0, tzinfo=timezone.utc) + now_bytes = int(now.timestamp()).to_bytes(4, byteorder="big") m = hmac.new(bytes.fromhex(key.secret), digestmod=hashlib.sha256) m.update(bytes.fromhex(challenge.challenge)) - m.update(now.encode('utf8')) - return KeyResponse(challenge.source, challenge.id, now, m.hexdigest()) + m.update(now_bytes) + return KeyResponse(challenge.source, challenge.id, now_bytes.hex(), m.hexdigest())