CasperSecurity

Current Path : /lib/python3/dist-packages/pymacaroons/serializers/
Upload File :
Current File : //lib/python3/dist-packages/pymacaroons/serializers/binary_serializer.py

from __future__ import unicode_literals

import binascii
from collections import namedtuple
import six
import struct
import sys
from base64 import urlsafe_b64encode

from pymacaroons.utils import (
    convert_to_bytes,
    convert_to_string,
    raw_b64decode,
)
from pymacaroons.serializers.base_serializer import BaseSerializer
from pymacaroons.exceptions import MacaroonSerializationException


PacketV2 = namedtuple('PacketV2', ['field_type', 'data'])


class BinarySerializer(BaseSerializer):

    PACKET_PREFIX_LENGTH = 4
    _LOCATION = 1
    _IDENTIFIER = 2
    _VID = 4
    _SIGNATURE = 6
    _EOS = 0

    def serialize(self, macaroon):
        return urlsafe_b64encode(
            self.serialize_raw(macaroon)).decode('ascii').rstrip('=')

    def serialize_raw(self, macaroon):
        from pymacaroons.macaroon import MACAROON_V1
        if macaroon.version == MACAROON_V1:
            return self._serialize_v1(macaroon)
        return self._serialize_v2(macaroon)

    def _serialize_v1(self, macaroon):
        combined = self._packetize(b'location', macaroon.location)
        combined += self._packetize(b'identifier', macaroon.identifier)

        for caveat in macaroon.caveats:
            combined += self._packetize(b'cid', caveat._caveat_id)

            if caveat._verification_key_id and caveat._location:
                combined += self._packetize(
                    b'vid', caveat._verification_key_id)
                combined += self._packetize(b'cl', caveat._location)

        combined += self._packetize(
            b'signature',
            binascii.unhexlify(macaroon.signature_bytes)
        )
        return combined

    def _serialize_v2(self, macaroon):
        from pymacaroons.macaroon import MACAROON_V2

        # https://github.com/rescrv/libmacaroons/blob/master/doc/format.txt
        data = bytearray()
        data.append(MACAROON_V2)
        if macaroon.location is not None:
            self._append_packet(data, self._LOCATION, convert_to_bytes(
                macaroon.location))
            self._append_packet(data, self._IDENTIFIER,
                                macaroon.identifier_bytes)
        self._append_packet(data, self._EOS)
        for c in macaroon.caveats:
            if c.location is not None:
                self._append_packet(data, self._LOCATION,
                                    convert_to_bytes(c.location))
            self._append_packet(data, self._IDENTIFIER, c.caveat_id_bytes)
            if c.verification_key_id is not None:
                self._append_packet(data, self._VID, convert_to_bytes(
                    c.verification_key_id))
            self._append_packet(data, self._EOS)
        self._append_packet(data, self._EOS)
        self._append_packet(data, self._SIGNATURE, binascii.unhexlify(
            macaroon.signature_bytes))
        return bytes(data)

    def deserialize(self, serialized):
        if len(serialized) == 0:
            raise ValueError('empty macaroon')
        serialized = convert_to_string(serialized)
        decoded = raw_b64decode(serialized)
        return self.deserialize_raw(decoded)

    def deserialize_raw(self, serialized):
        from pymacaroons.macaroon import MACAROON_V2
        from pymacaroons.exceptions import MacaroonDeserializationException

        first = six.byte2int(serialized[:1])
        if first == MACAROON_V2:
            return self._deserialize_v2(serialized)
        if _is_ascii_hex(first):
            return self._deserialize_v1(serialized)
        raise MacaroonDeserializationException(
            'cannot determine data format of binary-encoded macaroon')

    def _deserialize_v1(self, decoded):
        from pymacaroons.macaroon import Macaroon, MACAROON_V1
        from pymacaroons.caveat import Caveat
        from pymacaroons.exceptions import MacaroonDeserializationException

        macaroon = Macaroon(version=MACAROON_V1)

        index = 0

        while index < len(decoded):
            packet_length = int(
                struct.unpack(
                    b"4s",
                    decoded[index:index + self.PACKET_PREFIX_LENGTH]
                )[0],
                16
            )
            packet = decoded[
                index + self.PACKET_PREFIX_LENGTH:index + packet_length
            ]

            key, value = self._depacketize(packet)

            if key == b'location':
                macaroon.location = value
            elif key == b'identifier':
                macaroon.identifier = value
            elif key == b'cid':
                macaroon.caveats.append(Caveat(caveat_id=value,
                                               version=MACAROON_V1))
            elif key == b'vid':
                macaroon.caveats[-1].verification_key_id = value
            elif key == b'cl':
                macaroon.caveats[-1].location = value
            elif key == b'signature':
                macaroon.signature = binascii.hexlify(value)
            else:
                raise MacaroonDeserializationException(
                    'Key {key} not valid key for this format. '
                    'Value: {value}'.format(
                        key=key, value=value
                    )
                )

            index = index + packet_length

        return macaroon

    def _deserialize_v2(self, serialized):
        from pymacaroons.macaroon import Macaroon, MACAROON_V2
        from pymacaroons.caveat import Caveat
        from pymacaroons.exceptions import MacaroonDeserializationException

        # skip the initial version byte.
        serialized = serialized[1:]
        serialized, section = self._parse_section_v2(serialized)
        loc = ''
        if len(section) > 0 and section[0].field_type == self._LOCATION:
            loc = section[0].data.decode('utf-8')
            section = section[1:]
        if len(section) != 1 or section[0].field_type != self._IDENTIFIER:
            raise MacaroonDeserializationException('invalid macaroon header')
        macaroon = Macaroon(
            identifier=section[0].data,
            location=loc,
            version=MACAROON_V2,
        )
        while True:
            rest, section = self._parse_section_v2(serialized)
            serialized = rest
            if len(section) == 0:
                break
            cav = Caveat(version=MACAROON_V2)
            if len(section) > 0 and section[0].field_type == self._LOCATION:
                cav.location = section[0].data.decode('utf-8')
                section = section[1:]

            if len(section) == 0 or section[0].field_type != self._IDENTIFIER:
                raise MacaroonDeserializationException(
                    'no identifier in caveat')

            cav.caveat_id = section[0].data
            section = section[1:]
            if len(section) == 0:
                # First party caveat.
                if cav.location is not None:
                    raise MacaroonDeserializationException(
                        'location not allowed in first party caveat')
                macaroon.caveats.append(cav)
                continue

            if len(section) != 1:
                raise MacaroonDeserializationException(
                    'extra fields found in caveat')

            if section[0].field_type != self._VID:
                raise MacaroonDeserializationException(
                    'invalid field found in caveat')
            cav.verification_key_id = section[0].data
            macaroon.caveats.append(cav)
        serialized, packet = self._parse_packet_v2(serialized)
        if packet.field_type != self._SIGNATURE:
            raise MacaroonDeserializationException(
                'unexpected field found instead of signature')
        macaroon.signature = binascii.hexlify(packet.data)
        return macaroon

    def _packetize(self, key, data):
        # The 2 covers the space and the newline
        packet_size = self.PACKET_PREFIX_LENGTH + 2 + len(key) + len(data)
        # Ignore the first two chars, 0x
        packet_size_hex = hex(packet_size)[2:]

        if packet_size > 65535:
            raise MacaroonSerializationException(
                'Packet too long for serialization. '
                'Max length is 0xFFFF (65535). '
                'Packet length: 0x{hex_length} ({length}) '
                'Key: {key}'.format(
                    key=key,
                    hex_length=packet_size_hex,
                    length=packet_size
                )
            )

        header = packet_size_hex.zfill(4).encode('ascii')
        packet_content = key + b' ' + convert_to_bytes(data) + b'\n'
        packet = struct.pack(
            convert_to_bytes("4s%ds" % len(packet_content)),
            header,
            packet_content
        )
        return packet

    def _depacketize(self, packet):
        key = packet.split(b' ')[0]
        value = packet[len(key) + 1:-1]
        return (key, value)

    def _append_packet(self, data, field_type, packet_data=None):
        _encode_uvarint(data, field_type)
        if field_type != self._EOS:
            _encode_uvarint(data, len(packet_data))
            data.extend(packet_data)

    def _parse_section_v2(self, data):
        ''' Parses a sequence of packets in data.

        The sequence is terminated by a packet with a field type of EOS
        :param data bytes to be deserialized.
        :return: the rest of data and an array of packet V2
        '''

        from pymacaroons.exceptions import MacaroonDeserializationException

        prev_field_type = -1
        packets = []
        while True:
            if len(data) == 0:
                raise MacaroonDeserializationException(
                    'section extends past end of buffer')
            rest, packet = self._parse_packet_v2(data)
            if packet.field_type == self._EOS:
                return rest, packets
            if packet.field_type <= prev_field_type:
                raise MacaroonDeserializationException('fields out of order')
            packets.append(packet)
            prev_field_type = packet.field_type
            data = rest

    def _parse_packet_v2(self, data):
        ''' Parses a V2 data packet at the start of the given data.

        The format of a packet is as follows:

        field_type(varint) payload_len(varint) data[payload_len bytes]

        apart from EOS which has no payload_en or data (it's a single zero
        byte).

        :param data:
        :return: rest of data, PacketV2
        '''
        from pymacaroons.exceptions import MacaroonDeserializationException

        ft, n = _decode_uvarint(data)
        data = data[n:]
        if ft == self._EOS:
            return data, PacketV2(ft, None)
        payload_len, n = _decode_uvarint(data)
        data = data[n:]
        if payload_len > len(data):
            raise MacaroonDeserializationException(
                'field data extends past end of buffer')
        return data[payload_len:], PacketV2(ft, data[0:payload_len])


def _encode_uvarint(data, n):
    ''' Encodes integer into variable-length format into data.'''
    if n < 0:
        raise ValueError('only support positive integer')
    while True:
        this_byte = n & 0x7f
        n >>= 7
        if n == 0:
            data.append(this_byte)
            break
        data.append(this_byte | 0x80)


if sys.version_info.major == 2:
    def _decode_uvarint(data):
        ''' Decode a variable -length integer.

        Reads a sequence of unsigned integer byte and decodes them into an
        integer in variable-length format and returns it and the length read.
        '''
        n = 0
        shift = 0
        i = 0
        for b in data:
            b = ord(b)
            i += 1
            if b < 0x80:
                return n | b << shift, i
            n |= (b & 0x7f) << shift
            shift += 7
        raise Exception('cannot read uvarint from buffer')
else:
    def _decode_uvarint(data):
        ''' Decode a variable -length integer.

        Reads a sequence of unsigned integer byte and decodes them into an
        integer in variable-length format and returns it and the length read.
        '''
        n = 0
        shift = 0
        i = 0
        for b in data:
            i += 1
            if b < 0x80:
                return n | b << shift, i
            n |= (b & 0x7f) << shift
            shift += 7
        raise Exception('cannot read uvarint from buffer')


def _is_ascii_hex(b):
    if ord('0') <= b <= ord('9'):
        return True
    if ord('a') <= b <= ord('f'):
        return True
    return False
Hacker Blog, Shell İndir, Sql İnjection, XSS Attacks, LFI Attacks, Social Hacking, Exploit Bot, Proxy Tools, Web Shell, PHP Shell, Alfa Shell İndir, Hacking Training Set, DDoS Script, Denial Of Service, Botnet, RFI Attacks, Encryption
Telegram @BIBIL_0DAY