Beispiel #1
0
  def _SetupClients(self, n):
    res = {}
    for i in range(1, n + 1):
      client_id = "C.100000000000000%d" % i
      client = rdf_objects.ClientSnapshot(client_id=client_id)
      client.knowledge_base.os = "Windows"
      client.knowledge_base.fqdn = "host-%d.example.com" % i

      client.interfaces = [
          rdf_client_network.Interface(
              addresses=[
                  rdf_client_network.NetworkAddress(
                      address_type=rdf_client_network.NetworkAddress.Family.
                      INET,
                      packed_bytes=ipv6_utils.InetPtoN(socket.AF_INET,
                                                       "192.168.0.%d" % i)),
                  rdf_client_network.NetworkAddress(
                      address_type=rdf_client_network.NetworkAddress.Family.
                      INET6,
                      packed_bytes=ipv6_utils.InetPtoN(socket.AF_INET6,
                                                       "2001:abcd::%d" % i))
              ],
              mac_address=("aabbccddee0%d" % i).decode("hex"))
      ]
      res[client_id] = client
    return res
Beispiel #2
0
  def testClientSummaryToExportedNetworkInterfaceConverter(self):
    mac_address_bytes = b"123456"
    mac_address = text.Hexify(mac_address_bytes)

    summary = rdf_client.ClientSummary(interfaces=[
        rdf_client_network.Interface(
            mac_address=mac_address_bytes,
            ifname="eth0",
            addresses=[
                rdf_client_network.NetworkAddress(
                    address_type=rdf_client_network.NetworkAddress.Family.INET,
                    packed_bytes=socket.inet_pton(socket.AF_INET, "127.0.0.1"),
                ),
                rdf_client_network.NetworkAddress(
                    address_type=rdf_client_network.NetworkAddress.Family.INET,
                    packed_bytes=socket.inet_pton(socket.AF_INET, "10.0.0.1"),
                ),
                rdf_client_network.NetworkAddress(
                    address_type=rdf_client_network.NetworkAddress.Family.INET6,
                    packed_bytes=socket.inet_pton(socket.AF_INET6,
                                                  "2001:720:1500:1::a100"),
                )
            ])
    ])

    converter = client_summary.ClientSummaryToExportedNetworkInterfaceConverter(
    )
    results = list(converter.Convert(self.metadata, summary))
    self.assertLen(results, 1)
    self.assertEqual(results[0].mac_address, mac_address)
    self.assertEqual(results[0].ifname, "eth0")
    self.assertEqual(results[0].ip4_addresses, "127.0.0.1 10.0.0.1")
    self.assertEqual(results[0].ip6_addresses, "2001:720:1500:1::a100")
Beispiel #3
0
    def testClientMetadataPing(self):
        d = self.db

        client_id = self.InitializeClient()

        # Typical update on client ping.
        d.WriteClientMetadata(client_id,
                              last_ping=rdfvalue.RDFDatetime(200000000000),
                              last_clock=rdfvalue.RDFDatetime(210000000000),
                              last_ip=rdf_client_network.NetworkAddress(
                                  human_readable_address="8.8.8.8"),
                              last_foreman=rdfvalue.RDFDatetime(220000000000))

        res = d.MultiReadClientMetadata([client_id])
        self.assertEqual(len(res), 1)
        m1 = res[client_id]
        self.assertIsInstance(m1, rdf_objects.ClientMetadata)
        self.assertTrue(m1.fleetspeak_enabled)
        self.assertEqual(m1.ping, rdfvalue.RDFDatetime(200000000000))
        self.assertEqual(m1.clock, rdfvalue.RDFDatetime(210000000000))
        self.assertEqual(
            m1.ip,
            rdf_client_network.NetworkAddress(
                human_readable_address="8.8.8.8"))
        self.assertEqual(m1.last_foreman_time,
                         rdfvalue.RDFDatetime(220000000000))
Beispiel #4
0
def EnumerateInterfacesFromClient(args):
  """Enumerate all interfaces and collect their MAC addresses."""
  del args  # Unused

  libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("c"))
  ifa = Ifaddrs()
  p_ifa = ctypes.pointer(ifa)
  libc.getifaddrs(ctypes.pointer(p_ifa))

  addresses = {}
  macs = {}
  ifs = set()

  m = p_ifa
  while m:
    ifname = ctypes.string_at(m.contents.ifa_name)
    ifs.add(ifname)
    try:
      iffamily = ord(m.contents.ifa_addr[0])
      # TODO(hanuszczak): There are some Python 3-incompatible `chr` usages
      # here, they should be fixed.
      if iffamily == 0x2:  # AF_INET
        data = ctypes.cast(m.contents.ifa_addr, ctypes.POINTER(Sockaddrin))
        ip4 = bytes(list(data.contents.sin_addr))
        address_type = rdf_client_network.NetworkAddress.Family.INET
        address = rdf_client_network.NetworkAddress(
            address_type=address_type, packed_bytes=ip4)
        addresses.setdefault(ifname, []).append(address)

      if iffamily == 0x11:  # AF_PACKET
        data = ctypes.cast(m.contents.ifa_addr, ctypes.POINTER(Sockaddrll))
        addlen = data.contents.sll_halen
        macs[ifname] = bytes(list(data.contents.sll_addr[:addlen]))

      if iffamily == 0xA:  # AF_INET6
        data = ctypes.cast(m.contents.ifa_addr, ctypes.POINTER(Sockaddrin6))
        ip6 = bytes(list(data.contents.sin6_addr))
        address_type = rdf_client_network.NetworkAddress.Family.INET6
        address = rdf_client_network.NetworkAddress(
            address_type=address_type, packed_bytes=ip6)
        addresses.setdefault(ifname, []).append(address)
    except ValueError:
      # Some interfaces don't have a iffamily and will raise a null pointer
      # exception. We still want to send back the name.
      pass

    m = m.contents.ifa_next

  libc.freeifaddrs(p_ifa)

  for interface in ifs:
    mac = macs.setdefault(interface, b"")
    address_list = addresses.setdefault(interface, b"")
    args = {"ifname": interface}
    if mac:
      args["mac_address"] = mac
    if addresses:
      args["addresses"] = address_list
    yield rdf_client_network.Interface(**args)
Beispiel #5
0
def EnumerateInterfacesFromClient(args):
  """Enumerate all MAC addresses."""
  del args  # Unused

  libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("c"))
  ifa = Ifaddrs()
  p_ifa = ctypes.pointer(ifa)
  libc.getifaddrs(ctypes.pointer(p_ifa))

  addresses = {}
  macs = {}
  ifs = set()

  m = p_ifa
  while m:
    ifname = ctypes.string_at(m.contents.ifa_name)
    ifs.add(ifname)
    try:
      iffamily = ord(m.contents.ifa_addr[1])
      if iffamily == 0x2:  # AF_INET
        data = ctypes.cast(m.contents.ifa_addr, ctypes.POINTER(Sockaddrin))
        ip4 = "".join(map(chr, data.contents.sin_addr))
        address_type = rdf_client_network.NetworkAddress.Family.INET
        address = rdf_client_network.NetworkAddress(
            address_type=address_type, packed_bytes=ip4)
        addresses.setdefault(ifname, []).append(address)

      if iffamily == 0x12:  # AF_LINK
        data = ctypes.cast(m.contents.ifa_addr, ctypes.POINTER(Sockaddrdl))
        iflen = data.contents.sdl_nlen
        addlen = data.contents.sdl_alen
        macs[ifname] = "".join(
            map(chr, data.contents.sdl_data[iflen:iflen + addlen]))

      if iffamily == 0x1E:  # AF_INET6
        data = ctypes.cast(m.contents.ifa_addr, ctypes.POINTER(Sockaddrin6))
        ip6 = "".join(map(chr, data.contents.sin6_addr))
        address_type = rdf_client_network.NetworkAddress.Family.INET6
        address = rdf_client_network.NetworkAddress(
            address_type=address_type, packed_bytes=ip6)
        addresses.setdefault(ifname, []).append(address)
    except ValueError:
      # Some interfaces don't have a iffamily and will raise a null pointer
      # exception. We still want to send back the name.
      pass

    m = m.contents.ifa_next

  libc.freeifaddrs(p_ifa)

  for interface in ifs:
    mac = macs.setdefault(interface, "")
    address_list = addresses.setdefault(interface, "")
    args = {"ifname": interface}
    if mac:
      args["mac_address"] = mac
    if address_list:
      args["addresses"] = address_list
    yield rdf_client_network.Interface(**args)
Beispiel #6
0
def ParseIfaddrs(ifaddrs):
    """Parses contents of the intrusive linked list of `ifaddrs`.

  Args:
    ifaddrs: A pointer to the first node of `ifaddrs` linked list. Can be NULL.

  Returns:
    An iterator over instances of `rdf_client_network.Interface`.
  """
    precondition.AssertOptionalType(ifaddrs, ctypes.POINTER(Ifaddrs))

    ifaces = {}

    for ifaddr in IterIfaddrs(ifaddrs):
        ifname = ctypes.string_at(ifaddr.ifa_name).decode("utf-8")
        iface = ifaces.setdefault(ifname, rdf_client_network.Interface())
        iface.ifname = ifname

        if not ifaddr.ifa_addr:
            continue

        sockaddr = ctypes.cast(ifaddr.ifa_addr, ctypes.POINTER(Sockaddr))
        iffamily = sockaddr.contents.sa_family
        if iffamily == AF_INET:
            sockaddrin = ctypes.cast(ifaddr.ifa_addr,
                                     ctypes.POINTER(Sockaddrin))

            address = rdf_client_network.NetworkAddress()
            address.address_type = rdf_client_network.NetworkAddress.Family.INET
            address.packed_bytes = struct.pack("=L",
                                               sockaddrin.contents.sin_addr)
            iface.addresses.append(address)
        elif iffamily == AF_INET6:
            sockaddrin = ctypes.cast(ifaddr.ifa_addr,
                                     ctypes.POINTER(Sockaddrin6))

            address = rdf_client_network.NetworkAddress()
            address.address_type = rdf_client_network.NetworkAddress.Family.INET6
            address.packed_bytes = bytes(list(sockaddrin.contents.sin6_addr))
            iface.addresses.append(address)
        elif iffamily == AF_LINK:
            sockaddrdl = ctypes.cast(ifaddr.ifa_addr,
                                     ctypes.POINTER(Sockaddrdl))

            nlen = sockaddrdl.contents.sdl_nlen
            alen = sockaddrdl.contents.sdl_alen
            iface.mac_address = bytes(sockaddrdl.contents.sdl_data[nlen:nlen +
                                                                   alen])
        else:
            raise ValueError("Unexpected socket address family: %s" % iffamily)

    return itervalues(ifaces)
Beispiel #7
0
 def _ConvertIPs(self, io_tuples, interface, output_dict):
   for inputkey, outputkey in io_tuples:
     addresses = []
     if isinstance(interface[inputkey], list):
       for ip_address in interface[inputkey]:
         addresses.append(
             rdf_client_network.NetworkAddress(
                 human_readable_address=ip_address))
     else:
       addresses.append(
           rdf_client_network.NetworkAddress(
               human_readable_address=interface[inputkey]))
     output_dict[outputkey] = addresses
   return output_dict
Beispiel #8
0
    def testRdfFormatter(self):
        """Hints format RDF values with arbitrary values and attributes."""
        # Create a complex RDF value
        rdf = rdf_client.ClientSummary()
        rdf.system_info.system = "Linux"
        rdf.system_info.fqdn = "coreai.skynet.com"
        # Users (repeated)
        rdf.users = [rdf_client.User(username=u) for u in ("root", "jconnor")]
        # Interface (nested, repeated)
        addresses = [
            rdf_client_network.NetworkAddress(human_readable_address=a)
            for a in ("1.1.1.1", "2.2.2.2", "3.3.3.3")
        ]
        eth0 = rdf_client_network.Interface(ifname="eth0",
                                            addresses=addresses[:2])
        ppp0 = rdf_client_network.Interface(ifname="ppp0",
                                            addresses=addresses[2:3])
        rdf.interfaces = [eth0, ppp0]

        template = (
            "{system_info.system} {users.username} {interfaces.ifname} "
            "{interfaces.addresses.human_readable_address}\n")
        hinter = hints.Hinter(template=template)
        expected = "Linux root,jconnor eth0,ppp0 1.1.1.1,2.2.2.2,3.3.3.3"
        result = hinter.Render(rdf)
        self.assertEqual(expected, result)
Beispiel #9
0
def EnumerateInterfacesFromClient(args):
    """Enumerate all MAC addresses of all NICs.

  Args:
    args: Unused.

  Yields:
    `rdf_client_network.Interface` instances.
  """
    del args  # Unused.

    pythoncom.CoInitialize()
    for interface in wmi.WMI().Win32_NetworkAdapterConfiguration():
        addresses = []
        for ip_address in interface.IPAddress or []:
            addresses.append(
                rdf_client_network.NetworkAddress(
                    human_readable_address=ip_address))

        response = rdf_client_network.Interface(ifname=interface.Description)
        if interface.MACAddress:
            response.mac_address = binascii.unhexlify(
                interface.MACAddress.replace(":", ""))
        if addresses:
            response.addresses = addresses

        yield response
Beispiel #10
0
  def _TestInterfaces(self, client_nr):
    ip1 = rdf_client_network.NetworkAddress()
    ip1.human_readable_address = "192.168.0.%d" % client_nr

    ip2 = rdf_client_network.NetworkAddress()
    ip2.human_readable_address = "2001:abcd::%x" % client_nr

    mac1 = rdf_client_network.MacAddress.FromHumanReadableAddress(
        "aabbccddee%02x" % client_nr)
    mac2 = rdf_client_network.MacAddress.FromHumanReadableAddress(
        "bbccddeeff%02x" % client_nr)

    return [
        rdf_client_network.Interface(addresses=[ip1, ip2]),
        rdf_client_network.Interface(mac_address=mac1),
        rdf_client_network.Interface(mac_address=mac2),
    ]
Beispiel #11
0
 def EnumerateInterfaces(self, _):
     self.response_count += 1
     return [
         rdf_client_network.Interface(
             mac_address=b"123456",
             addresses=[
                 rdf_client_network.NetworkAddress(
                     human_readable_address="100.100.100.1"),
             ])
     ]
Beispiel #12
0
    def testIPv4(self):
        sample = rdf_client_network.NetworkAddress(
            human_readable_address="192.168.0.1")
        self.assertEqual(sample.address_type,
                         rdf_client_network.NetworkAddress.Family.INET)
        self.assertEqual(sample.packed_bytes,
                         socket.inet_pton(socket.AF_INET, "192.168.0.1"))

        self.assertEqual(sample.human_readable_address, "192.168.0.1")

        self.CheckRDFValue(self.rdfvalue_class(sample), sample)
Beispiel #13
0
    def testIPv4(self):
        sample = rdf_client_network.NetworkAddress(
            human_readable_address="192.168.0.1")
        self.assertEqual(sample.address_type,
                         rdf_client_network.NetworkAddress.Family.INET)
        # Equal to socket.inet_pton(socket.AF_INET, "192.168.0.1"), which is
        # unavailable on Windows.
        self.assertEqual(sample.packed_bytes, b"\xc0\xa8\x00\x01")

        self.assertEqual(sample.human_readable_address, "192.168.0.1")

        self.CheckRDFValue(self.rdfvalue_class(sample), sample)
Beispiel #14
0
  def testIPv6(self):
    ipv6_addresses = ["fe80::202:b3ff:fe1e:8329", "::1"]
    for address in ipv6_addresses:
      sample = rdf_client_network.NetworkAddress(human_readable_address=address)
      self.assertEqual(sample.address_type,
                       rdf_client_network.NetworkAddress.Family.INET6)
      self.assertEqual(sample.packed_bytes,
                       socket.inet_pton(socket.AF_INET6, address))

      self.assertEqual(sample.human_readable_address, address)

      self.CheckRDFValue(self.rdfvalue_class(sample), sample)
Beispiel #15
0
  def Run(self):
    # Fix the time to avoid regressions.
    with test_lib.FakeTime(42):
      client_id = self.SetupClient(0)

      ip = rdf_client_network.NetworkAddress(
          human_readable_address="192.168.100.42",
          address_type=rdf_client_network.NetworkAddress.Family.INET)
      data_store.REL_DB.WriteClientMetadata(client_id, last_ip=ip)

    self.Check(
        "GetLastClientIPAddress",
        args=client_plugin.ApiGetLastClientIPAddressArgs(client_id=client_id))
Beispiel #16
0
  def _SetupClients(self, n):
    res = {}
    for i in range(1, n + 1):
      client_id = "C.100000000000000%d" % i
      client = rdf_objects.ClientSnapshot(client_id=client_id)
      client.knowledge_base.os = "Windows"
      client.knowledge_base.fqdn = "host-%d.example.com" % i

      ipv4_addr = rdf_client_network.NetworkAddress(
          address_type=rdf_client_network.NetworkAddress.Family.INET,
          packed_bytes=ipaddress.IPv4Address("192.168.0.%d" % i).packed)
      ipv6_addr = rdf_client_network.NetworkAddress(
          address_type=rdf_client_network.NetworkAddress.Family.INET6,
          packed_bytes=ipaddress.IPv6Address("2001:abcd::%d" % i).packed)

      client.interfaces = [
          rdf_client_network.Interface(
              addresses=[ipv4_addr, ipv6_addr],
              mac_address=binascii.unhexlify("aabbccddee0%d" % i))
      ]
      res[client_id] = client
    return res
Beispiel #17
0
 def EnumerateInterfaces(self, _):
     self.response_count += 1
     return [
         rdf_client_network.Interface(
             mac_address="123456",
             addresses=[
                 rdf_client_network.NetworkAddress(
                     address_type=rdf_client_network.NetworkAddress.Family.
                     INET,
                     human_readable="100.100.100.1",
                     packed_bytes=socket.inet_pton(socket.AF_INET,
                                                   "100.100.100.1"),
                 )
             ])
     ]
Beispiel #18
0
  def testIPv6(self):
    ipv6_addresses = ["fe80::202:b3ff:fe1e:8329", "::1"]
    # Equal to socket.inet_pton(socket.AF_INET6, address), which is unavailable
    # on Windows.
    expected_addresses = [
        b"\xfe\x80\x00\x00\x00\x00\x00\x00\x02\x02\xb3\xff\xfe\x1e\x83\x29",
        b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
    ]
    for address, expected in zip(ipv6_addresses, expected_addresses):
      sample = rdf_client_network.NetworkAddress(human_readable_address=address)
      self.assertEqual(sample.address_type,
                       rdf_client_network.NetworkAddress.Family.INET6)
      self.assertEqual(sample.packed_bytes, expected)

      self.assertEqual(sample.human_readable_address, address)

      self.CheckRDFValue(self.rdfvalue_class(sample), sample)
Beispiel #19
0
def _WriteClientMetadata(client):
  """Store the AFF4 client metadata in the relational database."""
  client_ip = client.Get(client.Schema.CLIENT_IP)
  if client_ip:
    last_ip = rdf_client_network.NetworkAddress(
        human_readable_address=utils.SmartStr(client_ip))
  else:
    last_ip = None

  data_store.REL_DB.WriteClientMetadata(
      client.urn.Basename(),
      certificate=client.Get(client.Schema.CERT),
      fleetspeak_enabled=client.Get(client.Schema.FLEETSPEAK_ENABLED) or False,
      last_ping=client.Get(client.Schema.PING),
      last_clock=client.Get(client.Schema.CLOCK),
      last_ip=last_ip,
      last_foreman=client.Get(client.Schema.LAST_FOREMAN_TIME),
      first_seen=client.Get(client.Schema.FIRST_SEEN))
Beispiel #20
0
  def testRepeatedFields(self):
    """Test handling of protobuf repeated fields."""
    sample = rdf_client_network.Interface()

    # Add an invalid type.
    self.assertRaises(type_info.TypeValueError, sample.addresses.Append, 2)

    # Add an rdfvalue by kwargs.
    sample.addresses.Append(human_readable_address="127.0.0.1")

    self.assertEqual(sample.addresses[0].human_readable_address, "127.0.0.1")
    self.assertLen(sample.addresses, 1)

    # Add an rdfvalue.
    sample.addresses.Append(
        rdf_client_network.NetworkAddress(human_readable_address="1.2.3.4"))

    self.assertLen(sample.addresses, 2)
    self.assertEqual(sample.addresses[1].human_readable_address, "1.2.3.4")
Beispiel #21
0
    def Start(cls, args):
        del args  # Unused.

        pythoncom.CoInitialize()
        for interface in wmi.WMI().Win32_NetworkAdapterConfiguration():
            addresses = []
            for ip_address in interface.IPAddress or []:
                addresses.append(
                    rdf_client_network.NetworkAddress(
                        human_readable_address=ip_address))

            response = rdf_client_network.Interface(
                ifname=interface.Description)
            if interface.MACAddress:
                response.mac_address = binascii.unhexlify(
                    interface.MACAddress.replace(":", ""))
            if addresses:
                response.addresses = addresses

            yield response
Beispiel #22
0
    def Run(self):
        # Fix the time to avoid regressions.
        with test_lib.FakeTime(42):
            if data_store.RelationalDBReadEnabled():
                client_obj = self.SetupTestClientObject(0)
                client_id = client_obj.client_id

                ip = rdf_client_network.NetworkAddress(
                    human_readable_address="192.168.100.42",
                    address_type=rdf_client_network.NetworkAddress.Family.INET)
                data_store.REL_DB.WriteClientMetadata(client_id, last_ip=ip)
            else:
                client_urn = self.SetupClient(0)
                client_id = client_urn.Basename()

                with aff4.FACTORY.Open(client_id, mode="rw",
                                       token=self.token) as grr_client:
                    grr_client.Set(
                        grr_client.Schema.CLIENT_IP("192.168.100.42"))

        self.Check("GetLastClientIPAddress",
                   args=client_plugin.ApiGetLastClientIPAddressArgs(
                       client_id=client_id))
Beispiel #23
0
 def GenerateSample(self, number=0):
     return rdf_client_network.NetworkAddress(
         human_readable_address="192.168.0.%s" % number)
Beispiel #24
0
    def VerifyMessageSignature(self, response_comms, packed_message_list,
                               cipher, cipher_verified, api_version,
                               remote_public_key):
        """Verifies the message list signature.

    In the server we check that the timestamp is later than the ping timestamp
    stored with the client. This ensures that client responses can not be
    replayed.

    Args:
      response_comms: The raw response_comms rdfvalue.
      packed_message_list: The PackedMessageList rdfvalue from the server.
      cipher: The cipher object that should be used to verify the message.
      cipher_verified: If True, the cipher's signature is not verified again.
      api_version: The api version we should use.
      remote_public_key: The public key of the source.

    Returns:
      An rdf_flows.GrrMessage.AuthorizationState.
    """
        if (not cipher_verified
                and not cipher.VerifyCipherSignature(remote_public_key)):
            communicator.GRR_UNAUTHENTICATED_MESSAGES.Increment()
            return rdf_flows.GrrMessage.AuthorizationState.UNAUTHENTICATED

        try:
            client_id = cipher.cipher_metadata.source.Basename()
            metadata = data_store.REL_DB.ReadClientMetadata(client_id)
            client_time = packed_message_list.timestamp or rdfvalue.RDFDatetime(
                0)
            update_metadata = True

            # This used to be a strict check here so absolutely no out of
            # order messages would be accepted ever. Turns out that some
            # proxies can send your request with some delay even if the
            # client has already timed out (and sent another request in
            # the meantime, making the first one out of order). In that
            # case we would just kill the whole flow as a
            # precaution. Given the behavior of those proxies, this seems
            # now excessive and we have changed the replay protection to
            # only trigger on messages that are more than one hour old.
            if metadata and metadata.clock:
                stored_client_time = metadata.clock

                if client_time < stored_client_time - rdfvalue.Duration.From(
                        1, rdfvalue.HOURS):
                    logging.warning("Message desynchronized for %s: %s >= %s",
                                    client_id, stored_client_time, client_time)
                    # This is likely an old message
                    return rdf_flows.GrrMessage.AuthorizationState.DESYNCHRONIZED

                # Update the client and server timestamps only if the client time moves
                # forward.
                if client_time < stored_client_time:
                    logging.warning("Out of order message for %s: %s > %s",
                                    client_id, stored_client_time, client_time)
                    update_metadata = False

            communicator.GRR_AUTHENTICATED_MESSAGES.Increment()

            for label in data_store.REL_DB.ReadClientLabels(client_id):
                CLIENT_PINGS_BY_LABEL.Increment(fields=[label.name])

            if not update_metadata:
                return rdf_flows.GrrMessage.AuthorizationState.AUTHENTICATED

            source_ip = response_comms.orig_request.source_ip
            if source_ip:
                last_ip = rdf_client_network.NetworkAddress(
                    human_readable_address=response_comms.orig_request.
                    source_ip)
            else:
                last_ip = None

            data_store.REL_DB.WriteClientMetadata(
                client_id,
                last_ip=last_ip,
                last_clock=client_time,
                last_ping=rdfvalue.RDFDatetime.Now(),
                fleetspeak_enabled=False)

        except communicator.UnknownClientCertError:
            pass

        return rdf_flows.GrrMessage.AuthorizationState.AUTHENTICATED
Beispiel #25
0
    def testMultiple(self):
        foo_ipv4 = socket.inet_pton(socket.AF_INET, "192.0.2.1")
        foo_mac = b"\x00\xa0\xc9\x14\xc8\x29"

        foo_sockaddrin = self.osx.Sockaddrin()
        foo_sockaddrin.sin_family = self.osx.AF_INET
        foo_sockaddrin.sin_addr = struct.unpack("=L", foo_ipv4)[0]

        foo_sockaddrdl = self.osx.Sockaddrdl()
        foo_sockaddrdl.sdl_family = self.osx.AF_LINK
        foo_sockaddrdl.sdl_data[0:len(foo_mac)] = list(bytes(foo_mac))
        foo_sockaddrdl.sdl_nlen = 0
        foo_sockaddrdl.sdl_alen = len(foo_mac)

        bar_ipv6 = socket.inet_pton(socket.AF_INET6, "2607:f0d0:1002:51::4")
        bar_mac = b"\x48\x2c\x6a\x1e\x59\x3d"

        bar_sockaddrin = self.osx.Sockaddrin6()
        bar_sockaddrin.sin6_family = self.osx.AF_INET6
        bar_sockaddrin.sin6_addr = struct.unpack("=" + "B" * 16, bar_ipv6)

        bar_sockaddrdl = self.osx.Sockaddrdl()
        bar_sockaddrdl.sdl_family = self.osx.AF_LINK
        bar_sockaddrdl.sdl_data[0:len(foo_mac)] = list(bytes(bar_mac))
        bar_sockaddrdl.sdl_nlen = 0
        bar_sockaddrdl.sdl_alen = len(bar_mac)

        ifaddr = self.osx.Ifaddrs()
        ifaddr.ifa_next = None
        ifaddr.ifa_name = ctypes.create_string_buffer("foo")
        ifaddr.ifa_addr = ctypes.cast(ctypes.pointer(foo_sockaddrin),
                                      ctypes.POINTER(self.osx.Sockaddr))

        ifnext = ifaddr
        ifaddr = self.osx.Ifaddrs()
        ifaddr.ifa_next = ctypes.pointer(ifnext)
        ifaddr.ifa_name = ctypes.create_string_buffer("foo")
        ifaddr.ifa_addr = ctypes.cast(ctypes.pointer(foo_sockaddrdl),
                                      ctypes.POINTER(self.osx.Sockaddr))

        ifnext = ifaddr
        ifaddr = self.osx.Ifaddrs()
        ifaddr.ifa_next = ctypes.pointer(ifnext)
        ifaddr.ifa_name = ctypes.create_string_buffer("bar")
        ifaddr.ifa_addr = ctypes.cast(ctypes.pointer(bar_sockaddrdl),
                                      ctypes.POINTER(self.osx.Sockaddr))

        ifnext = ifaddr
        ifaddr = self.osx.Ifaddrs()
        ifaddr.ifa_next = ctypes.pointer(ifnext)
        ifaddr.ifa_name = ctypes.create_string_buffer("bar")
        ifaddr.ifa_addr = ctypes.cast(ctypes.pointer(bar_sockaddrin),
                                      ctypes.POINTER(self.osx.Sockaddr))

        expected_foo_iface = rdf_client_network.Interface(
            ifname="foo",
            mac_address=foo_mac,
            addresses=[
                rdf_client_network.NetworkAddress(
                    address_type=rdf_client_network.NetworkAddress.Family.INET,
                    packed_bytes=foo_ipv4),
            ])

        expected_bar_iface = rdf_client_network.Interface(
            ifname="bar",
            mac_address=bar_mac,
            addresses=[
                rdf_client_network.NetworkAddress(
                    address_type=rdf_client_network.NetworkAddress.Family.
                    INET6,
                    packed_bytes=bar_ipv6),
            ])

        results = list(self.osx.ParseIfaddrs(ctypes.pointer(ifaddr)))
        self.assertSameElements(results,
                                [expected_foo_iface, expected_bar_iface])
Beispiel #26
0
    def VerifyMessageSignature(self, response_comms, packed_message_list,
                               cipher, cipher_verified, api_version,
                               remote_public_key):
        """Verifies the message list signature.

    In the server we check that the timestamp is later than the ping timestamp
    stored with the client. This ensures that client responses can not be
    replayed.

    Args:
      response_comms: The raw response_comms rdfvalue.
      packed_message_list: The PackedMessageList rdfvalue from the server.
      cipher: The cipher object that should be used to verify the message.
      cipher_verified: If True, the cipher's signature is not verified again.
      api_version: The api version we should use.
      remote_public_key: The public key of the source.

    Returns:
      An rdf_flows.GrrMessage.AuthorizationState.
    """
        if (not cipher_verified
                and not cipher.VerifyCipherSignature(remote_public_key)):
            stats_collector_instance.Get().IncrementCounter(
                "grr_unauthenticated_messages")
            return rdf_flows.GrrMessage.AuthorizationState.UNAUTHENTICATED

        try:
            client_id = cipher.cipher_metadata.source
            try:
                client = self.client_cache.Get(client_id)
            except KeyError:
                client = aff4.FACTORY.Create(
                    client_id,
                    aff4.AFF4Object.classes["VFSGRRClient"],
                    mode="rw",
                    token=self.token)
                self.client_cache.Put(client_id, client)
                stats_collector_instance.Get().SetGaugeValue(
                    "grr_frontendserver_client_cache_size",
                    len(self.client_cache))

            ip = response_comms.orig_request.source_ip
            client.Set(client.Schema.CLIENT_IP(ip))

            # The very first packet we see from the client we do not have its clock
            remote_time = client.Get(
                client.Schema.CLOCK) or rdfvalue.RDFDatetime(0)
            client_time = packed_message_list.timestamp or rdfvalue.RDFDatetime(
                0)

            # This used to be a strict check here so absolutely no out of
            # order messages would be accepted ever. Turns out that some
            # proxies can send your request with some delay even if the
            # client has already timed out (and sent another request in
            # the meantime, making the first one out of order). In that
            # case we would just kill the whole flow as a
            # precaution. Given the behavior of those proxies, this seems
            # now excessive and we have changed the replay protection to
            # only trigger on messages that are more than one hour old.

            if client_time < remote_time - rdfvalue.Duration("1h"):
                logging.warning("Message desynchronized for %s: %s >= %s",
                                client_id, remote_time, client_time)
                # This is likely an old message
                return rdf_flows.GrrMessage.AuthorizationState.DESYNCHRONIZED

            stats_collector_instance.Get().IncrementCounter(
                "grr_authenticated_messages")

            # Update the client and server timestamps only if the client
            # time moves forward.
            if client_time > remote_time:
                client.Set(client.Schema.CLOCK, client_time)
                client.Set(client.Schema.PING, rdfvalue.RDFDatetime.Now())

                clock = client_time
                ping = rdfvalue.RDFDatetime.Now()

                for label in client.Get(client.Schema.LABELS, []):
                    stats_collector_instance.Get().IncrementCounter(
                        "client_pings_by_label", fields=[label.name])
            else:
                clock = None
                ping = None
                logging.warning("Out of order message for %s: %s >= %s",
                                client_id, remote_time, client_time)

            client.Flush()
            if data_store.RelationalDBEnabled():
                source_ip = response_comms.orig_request.source_ip
                if source_ip:
                    last_ip = rdf_client_network.NetworkAddress(
                        human_readable_address=response_comms.orig_request.
                        source_ip)
                else:
                    last_ip = None

                if ping or clock or last_ip:
                    try:
                        data_store.REL_DB.WriteClientMetadata(
                            client_id.Basename(),
                            last_ip=last_ip,
                            last_clock=clock,
                            last_ping=ping,
                            fleetspeak_enabled=False)
                    except db.UnknownClientError:
                        pass

        except communicator.UnknownClientCertError:
            pass

        return rdf_flows.GrrMessage.AuthorizationState.AUTHENTICATED