Example #1
0
    def parse(self, request, msg, name):
        if not isinstance(msg, dict):
            raise InvalidMessage('The message must be a dict')

        if 'type' not in msg:
            raise InvalidMessage('The type is missing')

        if isinstance(msg['type'], list):
            if len(msg['type']) != 1:
                raise InvalidMessage('Type is multivalued: %s' % msg['type'])
            msg_type = msg['type'][0]
        else:
            msg_type = msg['type']

        if 'value' not in msg:
            raise InvalidMessage('The value is missing')

        if isinstance(msg['value'], list):
            if len(msg['value']) != 1:
                raise InvalidMessage('Value is multivalued: %s' % msg['value'])
            msg_value = msg['value'][0]
        else:
            msg_value = msg['value']

        if msg_type not in list(self.types.keys()):
            raise UnknownMessageType("Type '%s' is unknown" % msg_type)

        if msg_type not in self.allowed:
            raise UnallowedMessage("Message type '%s' not allowed" % (
                                   msg_type,))

        handler = self.types[msg_type](request)
        handler.parse(msg_value, name)
        return handler
Example #2
0
    def parse(self, msg, name):
        """Parses the message.

        We check that the message is properly formatted.

        :param msg: a json-encoded value containing a JWS or JWE+JWS token

        :raises InvalidMessage: if the message cannot be parsed or validated

        :returns: A verified payload
        """

        try:
            jtok = JWT(jwt=msg)
        except Exception as e:
            raise InvalidMessage('Failed to parse message: %s' % str(e))

        try:
            token = jtok.token
            if isinstance(token, JWE):
                token.decrypt(self.kkstore.server_keys[KEY_USAGE_ENC])
                # If an encrypted payload is received then there must be
                # a nested signed payload to verify the provenance.
                payload = token.payload.decode('utf-8')
                token = JWS()
                token.deserialize(payload)
            elif isinstance(token, JWS):
                pass
            else:
                raise TypeError("Invalid Token type: %s" % type(jtok))

            # Retrieve client keys for later use
            self.client_keys = [
                JWK(**self._get_key(token.jose_header, KEY_USAGE_SIG)),
                JWK(**self._get_key(token.jose_header, KEY_USAGE_ENC))
            ]

            # verify token and get payload
            token.verify(self.client_keys[KEY_USAGE_SIG])
            claims = json_decode(token.payload)
        except Exception as e:
            logger.debug('Failed to validate message', exc_info=True)
            raise InvalidMessage('Failed to validate message: %s' % str(e))

        check_kem_claims(claims, name)
        self.name = name
        self.payload = claims.get('value')
        self.msg_type = 'kem'

        return {
            'type': self.msg_type,
            'value': {
                'kid': self.client_keys[KEY_USAGE_ENC].key_id,
                'claims': claims
            }
        }
Example #3
0
def check_kem_claims(claims, name):
    if 'sub' not in claims:
        raise InvalidMessage('Missing subject in payload')
    if claims['sub'] != name:
        raise InvalidMessage('Key name %s does not match subject %s' % (
            name, claims['sub']))
    if 'exp' not in claims:
        raise InvalidMessage('Missing expiration time in payload')
    if claims['exp'] - (10 * 60) > int(time.time()):
        raise InvalidMessage('Message expiration too far in the future')
    if claims['exp'] < int(time.time()):
        raise InvalidMessage('Message Expired')
Example #4
0
    def _get_key(self, header, usage):
        if 'kid' not in header:
            raise InvalidMessage("Missing key identifier")

        key = self.kkstore.find_key(header['kid'], usage)
        if key is None:
            raise UnknownPublicKey('Key found [kid:%s]' % header['kid'])
        return json_decode(key)
Example #5
0
    def parse(self, msg, name):
        """Parses a simple message

        :param req: ignored
        :param msg: the json-decoded value

        :raises UnknownMessageType: if the type is not 'simple'
        :raises InvalidMessage: if the message cannot be parsed or validated
        """

        # On requests we imply 'simple' if there is no input message
        if msg is None:
            return

        if not isinstance(msg, string_types):
            raise InvalidMessage("The 'value' attribute is not a string")

        self.payload = msg