예제 #1
0
  def _GetServerCipher(self):
    """Returns the cipher for self.server_name."""

    if self.server_cipher is not None:
      expiry = self.server_cipher_age + rdfvalue.Duration.From(1, rdfvalue.DAYS)
      if expiry > rdfvalue.RDFDatetime.Now():
        return self.server_cipher

    remote_public_key = self._GetRemotePublicKey(self.server_name)
    self.server_cipher = communicator.Cipher(self.common_name, self.private_key,
                                             remote_public_key)
    self.server_cipher_age = rdfvalue.RDFDatetime.Now()
    return self.server_cipher
예제 #2
0
    def EncodeMessages(self,
                       message_list,
                       result,
                       destination=None,
                       timestamp=None,
                       api_version=3):
        """Accepts a list of messages and encodes for transmission.

    This function signs and then encrypts the payload.

    Args:
       message_list: A MessageList rdfvalue containing a list of GrrMessages.
       result: A ClientCommunication rdfvalue which will be filled in.
       destination: The CN of the remote system this should go to.
       timestamp: A timestamp to use for the signed messages. If None - use the
         current time.
       api_version: The api version which this should be encoded in.

    Returns:
       A nonce (based on time) which is inserted to the encrypted payload. The
       client can verify that the server is able to decrypt the message and
       return the nonce.

    Raises:
       RuntimeError: If we do not support this api version.
    """
        if api_version not in [3]:
            raise RuntimeError("Unsupported api version: %s, expected 3." %
                               api_version)

        remote_public_key = self._GetRemotePublicKey(destination)
        cipher = communicator.Cipher(self.common_name, self.private_key,
                                     remote_public_key)

        # Make a nonce for this transaction
        if timestamp is None:
            self.timestamp = timestamp = int(time.time() * 1000000)

        packed_message_list = rdf_flows.PackedMessageList(timestamp=timestamp)
        self.EncodeMessageList(message_list, packed_message_list)

        result.encrypted_cipher_metadata = cipher.encrypted_cipher_metadata

        # Include the encrypted cipher.
        result.encrypted_cipher = cipher.encrypted_cipher

        serialized_message_list = packed_message_list.SerializeToBytes()

        # Encrypt the message symmetrically.
        # New scheme cipher is signed plus hmac over message list.
        result.packet_iv, result.encrypted = cipher.Encrypt(
            serialized_message_list)

        # This is to support older endpoints.
        result.hmac = cipher.HMAC(result.encrypted)

        # Newer endpoints only look at this HMAC. It is recalculated for each packet
        # in the session. Note that encrypted_cipher and encrypted_cipher_metadata
        # do not change between all packets in this session.
        result.full_hmac = cipher.HMAC(result.encrypted,
                                       result.encrypted_cipher,
                                       result.encrypted_cipher_metadata,
                                       result.packet_iv.SerializeToBytes(),
                                       struct.pack("<I", api_version))

        result.api_version = api_version

        if isinstance(result, rdfvalue.RDFValue):
            # Store the number of messages contained.
            result.num_messages = len(message_list)

        return timestamp