Пример #1
0
    def Run(self, unused_args):
        """Enumerate all MAC addresses."""
        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.NetworkAddress.Family.INET
                    address = rdf_client.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.NetworkAddress.Family.INET6
                    address = rdf_client.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
            self.SendReply(rdf_client.Interface(**args))
Пример #2
0
    def _SetupClients(self, n):
        res = {}
        for i in range(1, n + 1):
            client_id = "C.100000000000000%d" % i
            client = objects.Client()
            client.system = "Windows"
            client.hostname = "host-%d" % i
            client.fqdn = "host-%d.example.com" % i

            client.interfaces = [
                rdf_client.Interface(addresses=[
                    rdf_client.NetworkAddress(
                        address_type=rdf_client.NetworkAddress.Family.INET,
                        packed_bytes=ipv6_utils.InetPtoN(
                            socket.AF_INET, "192.168.0.%d" % i)),
                    rdf_client.NetworkAddress(
                        address_type=rdf_client.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
Пример #3
0
    def testClientMetadataPing(self):
        d = self.db

        client_id_1 = "C.fc413187fefa1dcf"
        self._InitializeClient(client_id_1)

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

        res = d.ReadClientMetadatas([client_id_1])
        self.assertEqual(len(res), 1)
        m1 = res[client_id_1]
        self.assertIsInstance(m1, 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.NetworkAddress(human_readable_address="8.8.8.8"))
        self.assertEqual(m1.last_foreman_time,
                         rdfvalue.RDFDatetime(220000000000))
Пример #4
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.NetworkAddress(
             human_readable_address=ip_address))
     else:
       addresses.append(rdf_client.NetworkAddress(
           human_readable_address=interface[inputkey]))
     output_dict[outputkey] = addresses
   return output_dict
Пример #5
0
    def testClientListReport(self):
        """Check that we can create and run a ClientList Report."""
        # Create some clients.
        client_ids = self.SetupClients(10)
        with aff4.FACTORY.Open(client_ids[0], token=self.token,
                               mode="rw") as client:
            interfaces = client.Schema.INTERFACES()
            interfaces.Append(addresses=[
                rdf_client.NetworkAddress(human_readable="1.1.1.1",
                                          address_type="INET")
            ],
                              mac_address="11:11:11:11:11:11",
                              ifname="eth0")
            client.Set(interfaces)
            client.Set(client.Schema.HOSTNAME("lawman"))

        # Also initialize a broken client with no hostname.
        with aff4.FACTORY.Open(client_ids[1], token=self.token,
                               mode="rw") as client:
            client.Set(client.Schema.CLIENT_INFO())

        # Create a report for all clients.
        report = reports.ClientListReport(token=self.token)
        report.Run()
        self.assertEqual(len(report.results), 10)
        hostnames = [x.get("Host") for x in report.results]
        self.assertTrue("lawman" in hostnames)

        report.SortResults("Host")
        self.assertEqual(len(report.AsDict()), 10)
        self.assertEqual(len(report.AsCsv().getvalue().splitlines()), 11)
        self.assertEqual(len(report.AsText().getvalue().splitlines()), 10)
        self.assertEqual(report.results[-1]["Interfaces"], "1.1.1.1")

        self.assertEqual(len(report.broken_clients), 1)
Пример #6
0
    def _TestInterfaces(self, client_nr):
        ip1 = rdf_client.NetworkAddress()
        ip1.human_readable_address = "192.168.0.%d" % client_nr

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

        mac1 = rdf_client.MacAddress()
        mac1.human_readable_address = "aabbccddee%02x" % client_nr

        mac2 = rdf_client.MacAddress()
        mac2.human_readable_address = "bbccddeeff%02x" % client_nr

        return [
            rdf_client.Interface(addresses=[ip1, ip2]),
            rdf_client.Interface(mac_address=mac1),
            rdf_client.Interface(mac_address=mac2),
        ]
Пример #7
0
  def testIPv4(self):
    sample = rdf_client.NetworkAddress(human_readable_address="192.168.0.1")
    self.assertEqual(sample.address_type, rdf_client.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)
Пример #8
0
 def EnumerateInterfaces(self, _):
   self.response_count += 1
   return [rdf_client.Interface(
       mac_address="123456",
       addresses=[
           rdf_client.NetworkAddress(
               address_type=rdf_client.NetworkAddress.Family.INET,
               human_readable="100.100.100.1",
               packed_bytes=socket.inet_pton(socket.AF_INET, "100.100.100.1"),)
       ])]
Пример #9
0
  def testIPv6(self):
    ipv6_addresses = ["fe80::202:b3ff:fe1e:8329", "::1"]
    for address in ipv6_addresses:
      sample = rdf_client.NetworkAddress(human_readable_address=address)
      self.assertEqual(sample.address_type,
                       rdf_client.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)
Пример #10
0
  def RunNetAdapterWMIQuery(self):
    pythoncom.CoInitialize()
    for interface in wmi.WMI().Win32_NetworkAdapterConfiguration(IPEnabled=1):
      addresses = []
      for ip_address in interface.IPAddress:
        addresses.append(rdf_client.NetworkAddress(
            human_readable_address=ip_address))

      args = {"ifname": interface.Description}
      args["mac_address"] = binascii.unhexlify(
          interface.MACAddress.replace(":", ""))
      if addresses:
        args["addresses"] = addresses

      yield args
Пример #11
0
  def Run(self, args):
    del args  # Unused.

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

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

      self.SendReply(response)
Пример #12
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.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))
Пример #13
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.NetworkAddress(
            human_readable_address="192.168.100.42",
            address_type=rdf_client.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))
Пример #14
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.node = "coreai.skynet.com"
    # Users (repeated)
    rdf.users = [rdf_client.User(username=u) for u in ("root", "jconnor")]
    # Interface (nested, repeated)
    addresses = [
        rdf_client.NetworkAddress(human_readable=a)
        for a in ("1.1.1.1", "2.2.2.2", "3.3.3.3")
    ]
    eth0 = rdf_client.Interface(ifname="eth0", addresses=addresses[:2])
    ppp0 = rdf_client.Interface(ifname="ppp0", addresses=addresses[2])
    rdf.interfaces = [eth0, ppp0]

    template = ("{system_info.system} {users.username} {interfaces.ifname} "
                "{interfaces.addresses.human_readable}\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)
Пример #15
0
 def GenerateSample(self, number=0):
   return rdf_client.NetworkAddress(
       human_readable_address="192.168.0.%s" % number)
Пример #16
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.STATS.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.STATS.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 < long(remote_time - rdfvalue.Duration("1h")):
                logging.warning("Message desynchronized for %s: %s >= %s",
                                client_id, long(remote_time), int(client_time))
                # This is likely an old message
                return rdf_flows.GrrMessage.AuthorizationState.DESYNCHRONIZED

            stats.STATS.IncrementCounter("grr_authenticated_messages")

            # Update the client and server timestamps only if the client
            # time moves forward.
            if client_time > long(remote_time):
                client.Set(client.Schema.CLOCK,
                           rdfvalue.RDFDatetime(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.STATS.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, long(remote_time), int(client_time))

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

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

        except communicator.UnknownClientCert:
            pass

        return rdf_flows.GrrMessage.AuthorizationState.AUTHENTICATED
Пример #17
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.STATS.IncrementCounter("grr_unauthenticated_messages")
            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)

            # 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("1h"):
                    logging.warning("Message desynchronized for %s: %s >= %s",
                                    client_id, long(stored_client_time),
                                    long(client_time))
                    # This is likely an old message
                    return rdf_flows.GrrMessage.AuthorizationState.DESYNCHRONIZED

                stats.STATS.IncrementCounter("grr_authenticated_messages")

                # 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, long(stored_client_time),
                                    long(client_time))
                    return rdf_flows.GrrMessage.AuthorizationState.AUTHENTICATED

            stats.STATS.IncrementCounter("grr_authenticated_messages")

            for label in data_store.REL_DB.ReadClientLabels(client_id):
                stats.STATS.IncrementCounter("client_pings_by_label",
                                             fields=[label.name])

            source_ip = response_comms.orig_request.source_ip
            if source_ip:
                last_ip = rdf_client.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.UnknownClientCert:
            pass

        return rdf_flows.GrrMessage.AuthorizationState.AUTHENTICATED