Validate uploaded key

merge-requests/30/head
Bob Mottram 2020-08-06 21:56:14 +01:00
parent e6ded5c795
commit 4b3e6dc65c
2 changed files with 84 additions and 0 deletions

View File

@ -194,6 +194,7 @@ from petnames import setPetName
from followingCalendar import addPersonToCalendar from followingCalendar import addPersonToCalendar
from followingCalendar import removePersonFromCalendar from followingCalendar import removePersonFromCalendar
from devices import E2EEdevicesCollection from devices import E2EEdevicesCollection
from devices import E2EEvalidDevice
import os import os
@ -5776,9 +5777,46 @@ class PubServer(BaseHTTPRequestHandler):
postBytes, boundary) postBytes, boundary)
return pageNumber return pageNumber
def _cryptoAPIreadJson(self) -> {}:
messageBytes = None
maxCryptoMessageLength = 10240
length = int(self.headers['Content-length'])
if length >= maxCryptoMessageLength:
print('WARN: post to crypto API is too long ' +
str(length) + ' bytes')
return {}
try:
messageBytes = self.rfile.read(length)
except SocketError as e:
if e.errno == errno.ECONNRESET:
print('WARN: POST messageBytes ' +
'connection reset by peer')
else:
print('WARN: POST messageBytes socket error')
return {}
except ValueError as e:
print('ERROR: POST messageBytes rfile.read failed')
print(e)
return {}
lenMessage = len(messageBytes)
if lenMessage > 10240:
print('WARN: post to crypto API is too long ' +
str(lenMessage) + ' bytes')
return {}
return json.loads(messageBytes)
def _cryptoAPI(self, path: str, authorized: bool) -> None: def _cryptoAPI(self, path: str, authorized: bool) -> None:
# TODO # TODO
if authorized and path.startswith('/api/v1/crypto/keys/upload'): if authorized and path.startswith('/api/v1/crypto/keys/upload'):
deviceKeys = self._cryptoAPIreadJson()
if not deviceKeys:
self._400()
return
if not E2EEvalidDevice(deviceKeys):
self._400()
return
self._200() self._200()
elif path.startswith('/api/v1/crypto/keys/query'): elif path.startswith('/api/v1/crypto/keys/query'):
self._200() self._200()

View File

@ -46,6 +46,52 @@ def E2EEremoveDevice(baseDir: str, nickname: str, domain: str,
return False return False
def E2EEvalidDevice(deviceJson: {}) -> bool:
"""Returns true if the given json contains valid device keys
"""
if not isinstance(deviceJson, dict):
return False
if not deviceJson.get('deviceId'):
return False
if not isinstance(deviceJson['deviceId'], str):
return False
if not deviceJson.get('type'):
return False
if not isinstance(deviceJson['type'], str):
return False
if deviceJson['type'] != 'Device':
return False
if not deviceJson.get('claim'):
return False
if not isinstance(deviceJson['claim'], str):
return False
if not deviceJson.get('fingerprintKey'):
return False
if not isinstance(deviceJson['fingerprintKey'], dict):
return False
if not deviceJson['fingerprintKey'].get('type'):
return False
if not isinstance(deviceJson['fingerprintKey']['type'], str):
return False
if not deviceJson['fingerprintKey'].get('publicKeyBase64'):
return False
if not isinstance(deviceJson['fingerprintKey']['publicKeyBase64'], str):
return False
if not deviceJson.get('identityKey'):
return False
if not isinstance(deviceJson['identityKey'], dict):
return False
if not deviceJson['identityKey'].get('type'):
return False
if not isinstance(deviceJson['identityKey']['type'], str):
return False
if not deviceJson['identityKey'].get('publicKeyBase64'):
return False
if not isinstance(deviceJson['identityKey']['publicKeyBase64'], str):
return False
return True
def E2EEaddDevice(baseDir: str, nickname: str, domain: str, def E2EEaddDevice(baseDir: str, nickname: str, domain: str,
deviceId: str, name: str, claimUrl: str, deviceId: str, name: str, claimUrl: str,
fingerprintPublicKey: str, fingerprintPublicKey: str,