Exemplo n.º 1
0
    def extractMessages( self, data, aes ):
        """
        Unpacks (i.e., decrypts and authenticates) protocol messages.

        The raw `data' coming directly from the wire is decrypted using `aes'
        and authenticated.  The payload (be it a session ticket or actual
        payload) is then returned as unencrypted protocol messages.  In case of
        invalid headers or HMACs, an exception is raised.
        """

        assert aes and (data is not None)

        self.recvBuf += data
        msgs = []

        # Keep trying to unpack as long as there is at least a header.
        while len(self.recvBuf) >= const.HDR_LENGTH:

            # If necessary, extract the header fields.
            if self.totalLen == self.payloadLen == self.flags == None:
                self.totalLen = pack.ntohs(aes.decrypt(self.recvBuf[16:18]))
                self.payloadLen = pack.ntohs(aes.decrypt(self.recvBuf[18:20]))
                self.flags = ord(aes.decrypt(self.recvBuf[20]))

                if not message.isSane(self.totalLen,
                                      self.payloadLen, self.flags):
                    raise base.PluggableTransportError("Invalid header.")

            # Parts of the message are still on the wire; waiting.
            if (len(self.recvBuf) - const.HDR_LENGTH) < self.totalLen:
                break

            rcvdHMAC = self.recvBuf[0:const.HMAC_SHA256_128_LENGTH]
            vrfyHMAC = mycrypto.HMAC_SHA256_128(self.recvHMAC,
                              self.recvBuf[const.HMAC_SHA256_128_LENGTH:
                              (self.totalLen + const.HDR_LENGTH)])

            if rcvdHMAC != vrfyHMAC:
                raise base.PluggableTransportError("Invalid message HMAC.")

            # Decrypt the message and remove it from the input buffer.
            extracted = aes.decrypt(self.recvBuf[const.HDR_LENGTH:
                         (self.totalLen + const.HDR_LENGTH)])[:self.payloadLen]
            msgs.append(message.new(payload=extracted, flags=self.flags))
            self.recvBuf = self.recvBuf[const.HDR_LENGTH + self.totalLen:]

            # Protocol message processed; now reset length fields.
            self.totalLen = self.payloadLen = self.flags = None

        return msgs
Exemplo n.º 2
0
    def extract(self, data, aes, hmacKey):
        """
        Extracts (i.e., decrypts and authenticates) protocol messages.

        The raw `data' coming directly from the wire is decrypted using `aes'
        and authenticated using `hmacKey'.  The payload is then returned as
        unencrypted protocol messages.  In case of invalid headers or HMACs, an
        exception is raised.
        """

        self.recvBuf += data
        msgs = []

        # Keep trying to unpack as long as there is at least a header.
        while len(self.recvBuf) >= const.HDR_LENGTH:

            # If necessary, extract the header fields.
            if self.totalLen == self.payloadLen == self.flags == None:
                self.totalLen = pack.ntohs(aes.decrypt(self.recvBuf[16:18]))
                self.payloadLen = pack.ntohs(aes.decrypt(self.recvBuf[18:20]))
                self.flags = ord(aes.decrypt(self.recvBuf[20]))

                if not isSane(self.totalLen, self.payloadLen, self.flags):
                    raise base.PluggableTransportError("Invalid header.")

            # Parts of the message are still on the wire; waiting.
            if (len(self.recvBuf) - const.HDR_LENGTH) < self.totalLen:
                break

            rcvdHMAC = self.recvBuf[0:const.HMAC_SHA256_128_LENGTH]
            vrfyHMAC = mycrypto.HMAC_SHA256_128(
                hmacKey,
                self.recvBuf[const.HMAC_SHA256_128_LENGTH:(self.totalLen +
                                                           const.HDR_LENGTH)])

            if rcvdHMAC != vrfyHMAC:
                raise base.PluggableTransportError("Invalid message HMAC.")

            # Decrypt the message and remove it from the input buffer.
            extracted = aes.decrypt(self.recvBuf[const.HDR_LENGTH:(
                self.totalLen + const.HDR_LENGTH)])[:self.payloadLen]
            msgs.append(ProtocolMessage(payload=extracted, flags=self.flags))
            self.recvBuf = self.recvBuf[const.HDR_LENGTH + self.totalLen:]

            # Protocol message processed; now reset length fields.
            self.totalLen = self.payloadLen = self.flags = None

        return msgs
Exemplo n.º 3
0
    def unpack(self, data, aes):

        # Input buffer which is not yet processed and forwarded.
        self.recvBuf += data
        fwdBuf = ""

        # Keep trying to unpack as long as there seems to be enough data.
        while len(self.recvBuf) >= const.HDR_LENGTH:

            # Extract length fields if we don't have them already.
            if self.totalLen == None:
                self.totalLen = pack.ntohs(aes.decrypt(self.recvBuf[16:18]))
                self.payloadLen = pack.ntohs(aes.decrypt(self.recvBuf[18:20]))

                # Abort immediately if the extracted lengths do not make sense.
                if not message.saneLengths(self.totalLen, self.payloadLen):
                    raise base.PluggableTransportError("Invalid message " \
                            "length(s): totalLen=%d, payloadLen=%d." % \
                            (self.totalLen, self.payloadLen))
                log.debug("Message header: totalLen=%d, payloadLen=%d." % \
                        (self.totalLen, self.payloadLen))

            if (len(self.recvBuf) - const.HDR_LENGTH) < self.totalLen:
                return fwdBuf

            # We have a full message; let's extract it.
            else:
                log.debug("Extracting fully received protocol message.")
                rcvdHMAC = self.recvBuf[0:const.HMAC_LENGTH]
                vrfyHMAC = mycrypto.MyHMAC_SHA256_128(self.recvHMAC, \
                        self.recvBuf[const.HMAC_LENGTH:(self.totalLen + \
                        const.HDR_LENGTH)])

                # Abort immediately if the HMAC is invalid.
                if rcvdHMAC != vrfyHMAC:
                    raise base.PluggableTransportError("Invalid HMAC!")

                fwdBuf += aes.decrypt(self.recvBuf[const.HDR_LENGTH: \
                        (self.totalLen+const.HDR_LENGTH)])[:self.payloadLen]

                self.recvBuf = self.recvBuf[const.HDR_LENGTH + self.totalLen:]
                # Protocol message extracted - resetting length fields.
                self.totalLen = self.payloadLen = None

        log.debug("Unpacked %d bytes of data: 0x%s..." % \
                (len(fwdBuf), fwdBuf[:10].encode('hex')))
        return fwdBuf
Exemplo n.º 4
0
    def unpack(self, data, aes):

        # Input buffer which is not yet processed and forwarded.
        self.recvBuf += data
        fwdBuf = ""

        # Keep trying to unpack as long as there seems to be enough data.
        while len(self.recvBuf) >= const.HDR_LENGTH:

            # Extract length fields if we don't have them already.
            if self.totalLen == None:
                self.totalLen = pack.ntohs(aes.decrypt(self.recvBuf[16:18]))
                self.payloadLen = pack.ntohs(aes.decrypt(self.recvBuf[18:20]))

                # Abort immediately if the extracted lengths do not make sense.
                if not message.saneLengths(self.totalLen, self.payloadLen):
                    raise base.PluggableTransportError(
                        "Invalid message " "length(s): totalLen=%d, payloadLen=%d." % (self.totalLen, self.payloadLen)
                    )
                log.debug("Message header: totalLen=%d, payloadLen=%d." % (self.totalLen, self.payloadLen))

            if (len(self.recvBuf) - const.HDR_LENGTH) < self.totalLen:
                return fwdBuf

            # We have a full message; let's extract it.
            else:
                log.debug("Extracting fully received protocol message.")
                rcvdHMAC = self.recvBuf[0 : const.HMAC_LENGTH]
                vrfyHMAC = mycrypto.MyHMAC_SHA256_128(
                    self.recvHMAC, self.recvBuf[const.HMAC_LENGTH : (self.totalLen + const.HDR_LENGTH)]
                )

                # Abort immediately if the HMAC is invalid.
                if rcvdHMAC != vrfyHMAC:
                    raise base.PluggableTransportError("Invalid HMAC!")

                fwdBuf += aes.decrypt(self.recvBuf[const.HDR_LENGTH : (self.totalLen + const.HDR_LENGTH)])[
                    : self.payloadLen
                ]

                self.recvBuf = self.recvBuf[const.HDR_LENGTH + self.totalLen :]
                # Protocol message extracted - resetting length fields.
                self.totalLen = self.payloadLen = None

        log.debug("Unpacked %d bytes of data: 0x%s..." % (len(fwdBuf), fwdBuf[:10].encode("hex")))
        return fwdBuf
Exemplo n.º 5
0
    def _get_ext_orport_command(self, buf):
        """
        Reads an Extended ORPort command from 'buf'. Returns (command,
        body) if it was well-formed, where 'command' is the Extended
        ORPort command type, and 'body' is its body.

        Throws NeedMoreData.
        """
        if len(buf) < AUTH_PROTOCOL_HEADER_LEN:
            raise NeedMoreData("Not enough data for header.")

        header = buf.peek(AUTH_PROTOCOL_HEADER_LEN)
        cmd = srlz.ntohs(header[:2])
        bodylen = srlz.ntohs(header[2:4])

        if (bodylen > len(buf) - AUTH_PROTOCOL_HEADER_LEN): # Not all here yet
            raise NeedMoreData("Not enough data for body.")

        # We have a whole command. Drain the header.
        buf.drain(4)
        body = buf.read(bodylen)

        return (cmd, body)
Exemplo n.º 6
0
 def getargsLen(self, string=None):
     """Return `argsLen` field from buffer."""
     return pack.ntohs(self.getMessageField(const.ARGS_TOTAL_LENGTH_POS,
                                            const.ARGS_TOTAL_LENGTH_LEN,
                                            string))
Exemplo n.º 7
0
 def getTotalLen(self, string=None):
     """Return `totalLen` field from buffer."""
     return pack.ntohs(self.getMessageField(const.TOTLENGTH_POS,
                                            const.TOTLENGTH_LEN,
                                            string))
Exemplo n.º 8
0
 def getPayloadLen(self, string=None):
     """Return `payloadLen` field from buffer."""
     return pack.ntohs(self.getMessageField(const.PAYLOAD_POS,
                                            const.PAYLOAD_LEN,
                                            string))
Exemplo n.º 9
0
 def getargsLen(self, string=None):
     """Return `argsLen` field from buffer."""
     return pack.ntohs(
         self.getMessageField(const.ARGS_TOTAL_LENGTH_POS,
                              const.ARGS_TOTAL_LENGTH_LEN, string))
Exemplo n.º 10
0
 def getTotalLen(self, string=None):
     """Return `totalLen` field from buffer."""
     return pack.ntohs(
         self.getMessageField(const.TOTLENGTH_POS, const.TOTLENGTH_LEN,
                              string))
Exemplo n.º 11
0
 def getPayloadLen(self, string=None):
     """Return `payloadLen` field from buffer."""
     return pack.ntohs(
         self.getMessageField(const.PAYLOAD_POS, const.PAYLOAD_LEN, string))