Verify third party ID server certificates
This commit is contained in:
parent
6ffbcf45c6
commit
b8dd5b1a2d
|
@ -397,13 +397,24 @@ class Auth(object):
|
|||
(EventTypes.ThirdPartyInvite, token,)
|
||||
)
|
||||
if not invite_event:
|
||||
logger.info("Failing 3pid invite because no invite found for token %s", token)
|
||||
return False
|
||||
try:
|
||||
public_key = join_third_party_invite["public_key"]
|
||||
key_validity_url = join_third_party_invite["key_validity_url"]
|
||||
if invite_event.content["public_key"] != public_key:
|
||||
logger.info(
|
||||
"Failing 3pid invite because public key invite: %s != join: %s",
|
||||
invite_event.content["public_key"],
|
||||
public_key
|
||||
)
|
||||
return False
|
||||
if invite_event.content["key_validity_url"] != key_validity_url:
|
||||
logger.info(
|
||||
"Failing 3pid invite because key_validity_url invite: %s != join: %s",
|
||||
invite_event.content["key_validity_url"],
|
||||
key_validity_url
|
||||
)
|
||||
return False
|
||||
verify_key = nacl.signing.VerifyKey(decode_base64(public_key))
|
||||
encoded_signature = join_third_party_invite["signature"]
|
||||
|
|
|
@ -22,11 +22,16 @@ from synapse.types import UserID, RoomAlias, RoomID
|
|||
from synapse.api.constants import (
|
||||
EventTypes, Membership, JoinRules, RoomCreationPreset,
|
||||
)
|
||||
from synapse.api.errors import StoreError, SynapseError
|
||||
from synapse.api.errors import AuthError, StoreError, SynapseError
|
||||
from synapse.util import stringutils, unwrapFirstError
|
||||
from synapse.util.async import run_on_reactor
|
||||
|
||||
from signedjson.sign import verify_signed_json
|
||||
from signedjson.key import decode_verify_key_bytes
|
||||
|
||||
from collections import OrderedDict
|
||||
from unpaddedbase64 import decode_base64
|
||||
|
||||
import logging
|
||||
import string
|
||||
|
||||
|
@ -614,12 +619,34 @@ class RoomMemberHandler(BaseHandler):
|
|||
)
|
||||
|
||||
if "mxid" in data:
|
||||
# TODO: Validate the response signature and such
|
||||
if "signatures" not in data:
|
||||
raise AuthError(401, "No signatures on 3pid binding")
|
||||
self.verify_any_signature(data, id_server)
|
||||
defer.returnValue(data["mxid"])
|
||||
|
||||
except IOError as e:
|
||||
logger.warn("Error from identity server lookup: %s" % (e,))
|
||||
defer.returnValue(None)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def verify_any_signature(self, data, server_hostname):
|
||||
if server_hostname not in data["signatures"]:
|
||||
raise AuthError(401, "No signature from server %s" % (server_hostname,))
|
||||
for key_name, signature in data["signatures"][server_hostname].items():
|
||||
key_data = yield self.hs.get_simple_http_client().get_json(
|
||||
"https://%s/_matrix/identity/api/v1/pubkey/%s" %
|
||||
(server_hostname, key_name,),
|
||||
)
|
||||
if "public_key" not in key_data:
|
||||
raise AuthError(401, "No public key named %s from %s" %
|
||||
(key_name, server_hostname,))
|
||||
verify_signed_json(
|
||||
data,
|
||||
server_hostname,
|
||||
decode_verify_key_bytes(key_name, decode_base64(key_data["public_key"]))
|
||||
)
|
||||
return
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def _make_and_store_3pid_invite(
|
||||
self,
|
||||
|
|
|
@ -24,7 +24,6 @@ from canonicaljson import encode_canonical_json
|
|||
from twisted.internet import defer, reactor, ssl
|
||||
from twisted.web.client import (
|
||||
Agent, readBody, FileBodyProducer, PartialDownloadError,
|
||||
HTTPConnectionPool,
|
||||
)
|
||||
from twisted.web.http_headers import Headers
|
||||
|
||||
|
@ -59,11 +58,8 @@ class SimpleHttpClient(object):
|
|||
# The default context factory in Twisted 14.0.0 (which we require) is
|
||||
# BrowserLikePolicyForHTTPS which will do regular cert validation
|
||||
# 'like a browser'
|
||||
pool = HTTPConnectionPool(reactor)
|
||||
pool.maxPersistentPerHost = 10
|
||||
self.agent = Agent(
|
||||
reactor,
|
||||
pool=pool,
|
||||
connectTimeout=15,
|
||||
contextFactory=hs.get_http_client_context_factory()
|
||||
)
|
||||
|
|
|
@ -63,7 +63,7 @@ def check_key_valid(http_client, event):
|
|||
event.content["third_party_invite"]["key_validity_url"],
|
||||
{"public_key": event.content["third_party_invite"]["public_key"]}
|
||||
)
|
||||
if not response["valid"]:
|
||||
raise AuthError(403, "Third party certificate was invalid")
|
||||
except IOError:
|
||||
except Exception:
|
||||
raise AuthError(502, "Third party certificate could not be checked")
|
||||
if "valid" not in response or not response["valid"]:
|
||||
raise AuthError(403, "Third party certificate was invalid")
|
||||
|
|
Loading…
Reference in New Issue