Example #1
0
    def do_validate_request(self, request):
        send_cors(request)

        # err = require_args(request, ('token', 'sid', 'client_secret'))
        err = require_args(request, ('token', 'sid'))
        if err:
            return err

        sid = request.args['sid'][0]
        tokenString = request.args['token'][0]
        if 'client_secret' in request.args:
            clientSecret = request.args['client_secret'][0]
        elif 'clientSecret' in request.args:
            clientSecret = request.args['clientSecret'][0]
        else:
            request.setResponseCode(400)
            return {'errcode': 'M_MISSING_PARAM', 'error':'No client_secret'}

        try:
            resp = self.sydent.validators.email.validateSessionWithToken(sid, clientSecret, tokenString)
        except IncorrectClientSecretException:
            return {'errcode': 'M_INCORRECT_CLIENT_SECRET',
                    'error': "Client secret does not match the one given when requesting the token"}
        except SessionExpiredException:
            return {'errcode': 'M_SESSION_EXPIRED',
                    'error': "This validation session has expired: call requestToken again"}

        if not resp:
            resp = {'success': False}

        return resp
    def render_POST(self, request):
        send_cors(request)
        err = require_args(request, ("private_key", "token", "mxid"))
        if err:
            return json.dumps(err)

        private_key_base64 = request.args['private_key'][0]
        token = request.args['token'][0]
        mxid = request.args['mxid'][0]

        sender = self.tokenStore.getSenderForToken(token)
        if sender is None:
            request.setResponseCode(404)
            return json.dumps({
                "errcode": "M_UNRECOGNIZED",
                "error": "Didn't recognized token",
            })

        to_sign = {
            "mxid": mxid,
            "sender": sender,
            "token": token,
        }
        try:
            private_key = signedjson.key.decode_signing_key_base64(
                "ed25519", "0", private_key_base64)
            signed = signedjson.sign.sign_json(to_sign, self.server_name,
                                               private_key)
        except:
            return json.dumps({
                "errcode": "M_UNKNOWN",
            })

        return json.dumps(signed)
Example #3
0
    def do_validate_request(self, request):
        send_cors(request)

        # err = require_args(request, ('token', 'sid', 'client_secret'))
        err = require_args(request, ('token', 'sid'))
        if err:
            return err

        sid = request.args['sid'][0]
        tokenString = request.args['token'][0]
        if 'client_secret' in request.args:
            clientSecret = request.args['client_secret'][0]
        elif 'clientSecret' in request.args:
            clientSecret = request.args['clientSecret'][0]
        else:
            request.setResponseCode(400)
            return {'success': False, 'errcode': 'M_MISSING_PARAM', 'error':'No client_secret'}

        try:
            resp = self.sydent.validators.email.validateSessionWithToken(sid, clientSecret, tokenString)
        except IncorrectClientSecretException:
            return {'success': False, 'errcode': 'M_INCORRECT_CLIENT_SECRET',
                    'error': "Client secret does not match the one given when requesting the token"}
        except SessionExpiredException:
            return {'success': False, 'errcode': 'M_SESSION_EXPIRED',
                    'error': "This validation session has expired: call requestToken again"}

        if not resp:
            resp = {'success': False}

        return resp
    def render_POST(self, request):
        send_cors(request)
        #err = require_args(request, ('sid', 'client_secret', 'mxid'))
        err = require_args(request, ('sid', 'mxid'))
        if err:
            return err

        sid = request.args['sid'][0]
        mxid = request.args['mxid'][0]
        if 'client_secret' in request.args:
            clientSecret = request.args['client_secret'][0]
        elif 'clientSecret' in request.args:
            clientSecret = request.args['clientSecret'][0]
        else:
            request.setResponseCode(400)
            return {'errcode': 'M_MISSING_PARAM', 'error':'No client_secret'}

        # Return the same error for not found / bad client secret otherwise people can get information about
        # sessions without knowing the secret
        noMatchError = {'errcode': 'M_NO_VALID_SESSION',
                        'error': "No valid session was found matching that sid and client secret"}

        try:
            res = self.sydent.threepidBinder.addBinding(sid, clientSecret, mxid)
            return res
        except IncorrectClientSecretException:
            return noMatchError
        except SessionExpiredException:
            return {'errcode': 'M_SESSION_EXPIRED',
                    'error': "This validation session has expired: call requestToken again"}
        except InvalidSessionIdException:
            return noMatchError
        except SessionNotValidatedException:
            return {'errcode': 'M_SESSION_NOT_VALIDATED',
                    'error': "This validation session has not yet been completed"}
Example #5
0
    def render_GET(self, request):
        err = require_args(request, ("public_key",))
        if err:
            return json.dumps(err)
        publicKey = request.args["public_key"][0]

        return json.dumps({
            'valid': self.joinTokenStore.validateEphemeralPublicKey(publicKey),
        })
Example #6
0
    def render_GET(self, request):
        err = require_args(request, ("public_key",))
        if err:
            return json.dumps(err)

        pubKey = self.sydent.keyring.ed25519.verify_key
        pubKeyBase64 = encode_base64(pubKey.encode())

        return json.dumps({'valid': request.args["public_key"][0] == pubKeyBase64})
Example #7
0
    def render_GET(self, request):
        err = require_args(request, ("public_key", ))
        if err:
            return json.dumps(err)
        publicKey = request.args["public_key"][0]

        return json.dumps({
            'valid':
            self.joinTokenStore.validateEphemeralPublicKey(publicKey),
        })
Example #8
0
    def render_GET(self, request):
        err = require_args(request, ("public_key", ))
        if err:
            return json.dumps(err)

        pubKey = self.sydent.keyring.ed25519.verify_key
        pubKeyBase64 = encode_base64(pubKey.encode())

        return json.dumps(
            {'valid': request.args["public_key"][0] == pubKeyBase64})
Example #9
0
    def render_POST(self, request):
        send_cors(request)

        # error = require_args(request, ('email', 'client_secret', 'send_attempt'))
        error = require_args(request, ('email',))
        if error:
            request.setResponseCode(400)
            return error

        # look for both camelcase and underscores for transition
        if 'client_secret' in request.args:
            clientSecret = request.args['client_secret'][0]
        elif 'clientSecret' in request.args:
            clientSecret = request.args['clientSecret'][0]
        else:
            request.setResponseCode(400)
            return {'errcode': 'M_MISSING_PARAM', 'error':'No client_secret'}

        if 'send_attempt' in request.args:
            sendAttempt = request.args['send_attempt'][0]
        elif 'sendAttempt' in request.args:
            sendAttempt = request.args['sendAttempt'][0]
        else:
            request.setResponseCode(400)
            return {'errcode': 'M_MISSING_PARAM', 'error':'No send_attempt'}

        email = request.args['email'][0]

        ipaddress = self.sydent.ip_from_request(request)

        nextLink = None
        if 'next_link' in request.args:
            nextLink = request.args['next_link'][0]

        resp = None

        try:
            sid = self.sydent.validators.email.requestToken(
                email, clientSecret, sendAttempt, nextLink, ipaddress=ipaddress
            )
        except EmailAddressException:
            request.setResponseCode(400)
            resp = {'errcode': 'M_INVALID_EMAIL', 'error':'Invalid email address'}
        except EmailSendException:
            request.setResponseCode(500)
            resp = {'errcode': 'M_EMAIL_SEND_ERROR', 'error': 'Failed to send email'}

        if not resp:
            resp = {'success': True, 'sid': sid}

        return resp
Example #10
0
    def render_POST(self, request):
        send_cors(request)

        # error = require_args(request, ('email', 'client_secret', 'send_attempt'))
        error = require_args(request, ('email',))
        if error:
            request.setResponseCode(400)
            return error

        # look for both camelcase and underscores for transition
        if 'client_secret' in request.args:
            clientSecret = request.args['client_secret'][0]
        elif 'clientSecret' in request.args:
            clientSecret = request.args['clientSecret'][0]
        else:
            request.setResponseCode(400)
            return {'errcode': 'M_MISSING_PARAM', 'error':'No client_secret'}

        if 'send_attempt' in request.args:
            sendAttempt = request.args['send_attempt'][0]
        elif 'sendAttempt' in request.args:
            sendAttempt = request.args['sendAttempt'][0]
        else:
            request.setResponseCode(400)
            return {'errcode': 'M_MISSING_PARAM', 'error':'No send_attempt'}

        email = request.args['email'][0]

        ipaddress = self.sydent.ip_from_request(request)

        nextLink = None
        if 'next_link' in request.args:
            nextLink = request.args['next_link'][0]

        resp = None

        try:
            sid = self.sydent.validators.email.requestToken(
                email, clientSecret, sendAttempt, nextLink, ipaddress=ipaddress
            )
        except EmailAddressException:
            request.setResponseCode(400)
            resp = {'errcode': 'M_INVALID_EMAIL', 'error':'Invalid email address'}
        except EmailSendException:
            request.setResponseCode(500)
            resp = {'errcode': 'M_EMAIL_SEND_ERROR', 'error': 'Failed to send email'}

        if not resp:
            resp = {'success': True, 'sid': sid}

        return resp
    def render_GET(self, request):
        # err = require_args(request, ('sid', 'client_secret'))
        err = require_args(request, ('sid', ))
        if err:
            return err

        sid = request.args['sid'][0]
        #clientSecret = request.args['client_secret'][0]

        if 'client_secret' in request.args:
            clientSecret = request.args['client_secret'][0]
        elif 'clientSecret' in request.args:
            clientSecret = request.args['clientSecret'][0]
        else:
            request.setResponseCode(400)
            return {'errcode': 'M_MISSING_PARAM', 'error': 'No client_secret'}

        valSessionStore = ThreePidValSessionStore(self.sydent)

        noMatchError = {
            'errcode':
            'M_NO_VALID_SESSION',
            'error':
            "No valid session was found matching that sid and client secret"
        }

        try:
            s = valSessionStore.getValidatedSession(sid, clientSecret)
        except IncorrectClientSecretException:
            return noMatchError
        except SessionExpiredException:
            return {
                'errcode':
                'M_SESSION_EXPIRED',
                'error':
                "This validation session has expired: call requestToken again"
            }
        except InvalidSessionIdException:
            return noMatchError
        except SessionNotValidatedException:
            return {
                'errcode': 'M_SESSION_NOT_VALIDATED',
                'error': "This validation session has not yet been completed"
            }

        return {
            'medium': s.medium,
            'address': s.address,
            'validated_at': s.mtime
        }
Example #12
0
    def render_GET(self, request):
        send_cors(request)
        err = require_args(request, ('medium', 'address'))
        if err:
            return err

        medium = request.args['medium'][0]
        address = request.args['address'][0]

        globalAssocStore = GlobalAssociationStore(self.sydent)

        sgassoc = globalAssocStore.signedAssociationStringForThreepid(medium, address)

        if not sgassoc:
            return json.dumps({})

        return sgassoc.encode('utf8')
Example #13
0
    def render_GET(self, request):
        send_cors(request)
        err = require_args(request, ('medium', 'address'))
        if err:
            return err

        medium = request.args['medium'][0]
        address = request.args['address'][0]

        globalAssocStore = GlobalAssociationStore(self.sydent)

        sgassoc = globalAssocStore.signedAssociationStringForThreepid(medium, address)

        if not sgassoc:
            return json.dumps({})

        sgassoc = json.loads(sgassoc.encode('utf8'))
        if not self.sydent.server_name in sgassoc['signatures']:
            # We have not yet worked out what the proper trust model should be.
            #
            # Maybe clients implicitly trust a server they talk to (and so we
            # should sign every assoc we return as ourselves, so they can
            # verify this).
            #
            # Maybe clients really want to know what server did the original
            # verification, and want to only know exactly who signed the assoc.
            #
            # Until we work out what we should do, sign all assocs we return as
            # ourself. This is vaguely ok because there actually is only one
            # identity server, but it happens to have two names (matrix.org and
            # vector.im), and so we're not really lying too much.
            #
            # We do this when we return assocs, not when we receive them over
            # replication, so that we can undo this decision in the future if
            # we wish, without having destroyed the raw underlying data.
            sgassoc = signedjson.sign.sign_json(
                sgassoc,
                self.sydent.server_name,
                self.sydent.keyring.ed25519
            )
        return json.dumps(sgassoc)
Example #14
0
    def render_POST(self, request):
        send_cors(request)
        err = require_args(request, ("private_key", "token", "mxid"))
        if err:
            return json.dumps(err)

        private_key_base64 = request.args['private_key'][0]
        token = request.args['token'][0]
        mxid = request.args['mxid'][0]

        sender = self.tokenStore.getSenderForToken(token)
        if sender is None:
            request.setResponseCode(404)
            return json.dumps({
                "errcode": "M_UNRECOGNIZED",
                "error": "Didn't recognized token",
            })

        to_sign = {
            "mxid": mxid,
            "sender": sender,
            "token": token,
        }
        try:
            private_key = signedjson.key.decode_signing_key_base64(
                "ed25519",
                "0",
                private_key_base64
            )
            signed = signedjson.sign.sign_json(
                to_sign,
                self.server_name,
                private_key
            )
        except:
            return json.dumps({
                "errcode": "M_UNKNOWN",
            })

        return json.dumps(signed)
Example #15
0
    def render_GET(self, request):
        # err = require_args(request, ('sid', 'client_secret'))
        err = require_args(request, ('sid',))
        if err:
            return err

        sid = request.args['sid'][0]
        #clientSecret = request.args['client_secret'][0]

        if 'client_secret' in request.args:
            clientSecret = request.args['client_secret'][0]
        elif 'clientSecret' in request.args:
            clientSecret = request.args['clientSecret'][0]
        else:
            request.setResponseCode(400)
            return {'errcode': 'M_MISSING_PARAM', 'error':'No client_secret'}

        valSessionStore = ThreePidValSessionStore(self.sydent)

        noMatchError = {'errcode': 'M_NO_VALID_SESSION',
                        'error': "No valid session was found matching that sid and client secret"}

        try:
            s = valSessionStore.getValidatedSession(sid, clientSecret)
        except IncorrectClientSecretException:
            return noMatchError
        except SessionExpiredException:
            return {'errcode': 'M_SESSION_EXPIRED',
                    'error': "This validation session has expired: call requestToken again"}
        except InvalidSessionIdException:
            return noMatchError
        except SessionNotValidatedException:
            return {'errcode': 'M_SESSION_NOT_VALIDATED',
                    'error': "This validation session has not yet been completed"}

        return { 'medium': s.medium, 'address': s.address, 'validated_at': s.mtime }
Example #16
0
    def render_POST(self, request):
        send_cors(request)
        err = require_args(request, ("medium", "address", "room_id", "sender",))
        if err:
            return json.dumps(err)
        medium = request.args["medium"][0]
        address = request.args["address"][0]
        roomId = request.args["room_id"][0]
        sender = request.args["sender"][0]

        globalAssocStore = GlobalAssociationStore(self.sydent)
        mxid = globalAssocStore.getMxid(medium, address)
        if mxid:
            request.setResponseCode(400)
            return json.dumps({
                "errcode": "THREEPID_IN_USE",
                "error": "Binding already known",
                "mxid": mxid,
            })

        if medium != "email":
            request.setResponseCode(400)
            return json.dumps({
                "errcode": "M_UNRECOGNIZED",
                "error": "Didn't understand medium '%s'" % (medium,),
            })

        token = self._randomString(128)

        tokenStore = JoinTokenStore(self.sydent)

        ephemeralPrivateKey = nacl.signing.SigningKey.generate()
        ephemeralPublicKey = ephemeralPrivateKey.verify_key

        ephemeralPrivateKeyBase64 = encode_base64(ephemeralPrivateKey.encode(), True)
        ephemeralPublicKeyBase64 = encode_base64(ephemeralPublicKey.encode(), True)

        tokenStore.storeEphemeralPublicKey(ephemeralPublicKeyBase64)
        tokenStore.storeToken(medium, address, roomId, sender, token)

        substitutions = {}
        for key, values in request.args.items():
            if len(values) == 1 and type(values[0]) == str:
                substitutions[key] = values[0]
        substitutions["token"] = token

        required = [
            'sender_display_name',
            'token',
            'room_name',
            'bracketed_room_name',
            'room_avatar_url',
            'sender_display_name',
            'guest_user_id',
            'guest_access_token',
        ]
        for k in required:
            substitutions.setdefault(k, '')

        substitutions["ephemeral_private_key"] = ephemeralPrivateKeyBase64
        if substitutions["room_name"] != '':
            substitutions["bracketed_room_name"] = "(%s)" % substitutions["room_name"]

        subject_header = Header(self.sydent.cfg.get('email', 'email.invite.subject', raw=True) % substitutions, 'utf8')
        substitutions["subject_header_value"] = subject_header.encode()

        sendEmail(self.sydent, "email.invite_template", address, substitutions)

        pubKey = self.sydent.keyring.ed25519.verify_key
        pubKeyBase64 = encode_base64(pubKey.encode())

        baseUrl = "%s/_matrix/identity/api/v1" % (self.sydent.cfg.get('http', 'client_http_base'),)

        keysToReturn = []
        keysToReturn.append({
            "public_key": pubKeyBase64,
            "key_validity_url": baseUrl + "/pubkey/isvalid",
        })
        keysToReturn.append({
            "public_key": ephemeralPublicKeyBase64,
            "key_validity_url": baseUrl + "/pubkey/ephemeral/isvalid",
        })

        resp = {
            "token": token,
            "public_key": pubKeyBase64,
            "public_keys": keysToReturn,
            "display_name": self.redact(address),
        }

        return json.dumps(resp)