Beispiel #1
0
    def GetNextDhcpPacket(self):
        if self.filedesc and self.binary:
            packet = dhcp_packet.DhcpPacket()
            data = self.filedesc.read(4096)
            packet.DecodePacket(data)
            return packet

        elif self.filedesc and not self.binary:
            packet = dhcp_packet.DhcpPacket()
            for line in self.filedesc:
                packet.AddLine(line)
            return packet
Beispiel #2
0
        def dhcp_inform(self, packet):
            mac = decode_mac(packet.GetOption("chaddr"))
            client_ip = ".".join(map(str, packet.GetOption("ciaddr")))
            requested_options = packet.GetOption("parameter_request_list")

            opt_vals = self.__db.retrieve_dhcp_options(
                mac=mac, address=client_ip, option_ids=requested_options)

            ack = dhcp_packet.DhcpPacket()
            ack.CreateDhcpAckPacketFrom(packet)

            # FIXME: check the RFC on 'hops'
            hops = packet.GetOption("hops")
            if hops:
                ack.SetOption("hops", hops)

            self.assign_dhcp_options(options=opt_vals,
                                     requested=requested_options,
                                     packet=ack)

            ack.DeleteOption("yiaddr")
            ack.DeleteOption("ip_address_lease_time")

            # send an ack
            self.SendPacket(ack)
Beispiel #3
0
    def HandleDhcpDiscover(self, packet):
        clientMacAddress = ":".join('%02x' % i
                                    for i in packet.GetHardwareAddress())
        try:
            clientAddress = self.get_address(clientMacAddress)
        except:
            return

        self.memory[clientMacAddress] = clientAddress

        packet.SetMultipleOptions({'ip_address_lease_time':
                                   [0, 2, 0,
                                    0]})  # Think it means 2*256*256 seconds :)
        offer = dhcp_packet.DhcpPacket()
        offer.CreateDhcpOfferPacketFrom(packet)
        self.addBootInfoAndBroadcast(offer, clientAddress)
Beispiel #4
0
    def HandlePacket(self):
        if not self.sockets_initialized:
            self._open_sockets()
        rlist, wlist, xlist = select.select(self.dhcp_sockets, [], [])
        s = rlist[0]
        data, sender = s.recvfrom(self.BUFLEN)

        packet = dhcp_packet.DhcpPacket()
        try:
            packet.DecodePacket(data)
        except Exception as e:
            print_exception(e)
            b64_data = base64.b64encode(data)
            print("FAILED TO PARSE: %r: %r" % (e, b64_data))
            dhcp.get_logger().log(dhcp.logging.ERROR,
                                  "IGN/UNPARSABLE: %r" % b64_data)

            if raven_client:
                raven_client.captureMessage(
                    "Failed to parse invalid DHCP packet",
                    tags={"server": self.dhcp_socket_info[s]["address"]},
                    level=dhcp.logging.ERROR,
                    extra={
                        "b64_data": b64_data,
                        "server_ip_address":
                        self.dhcp_socket_info[s]["address"],
                        "server_interface": self.dhcp_socket_info[s],
                        "t_name": "INVALID",
                        "recvd_from": sender,
                    },
                )
            return

        packet.set_sender(sender)
        packet.set_recv_interface(self.dhcp_socket_info[s])

        packet_type = get_packet_type(packet)
        if packet_type is False:
            log_packet(packet, prefix="IGN/INVALID TYPE:", raw=True)
        if not packet.IsDhcpPacket():
            log_packet(packet, prefix="IGN/INVALID PKT:", raw=True)
        self.QueuePacket(packet, packet_type)
Beispiel #5
0
    def GetNextDhcpPacket(self, timeout=60):
        data = ""

        while data == "":

            data_input, data_output, data_except = select.select(
                [self.dhcp_socket], [], [], timeout)

            if (data_input != []):
                (data, source_address) = self.dhcp_socket.recvfrom(2048)
            else:
                return None

            if data != "":
                packet = dhcp_packet.DhcpPacket()
                packet.source_address = source_address
                packet.DecodePacket(data)

                self.HandleDhcpAll(packet)

                if packet.IsDhcpDiscoverPacket():
                    self.HandleDhcpDiscover(packet)
                elif packet.IsDhcpRequestPacket():
                    self.HandleDhcpRequest(packet)
                elif packet.IsDhcpDeclinePacket():
                    self.HandleDhcpDecline(packet)
                elif packet.IsDhcpReleasePacket():
                    self.HandleDhcpRelease(packet)
                elif packet.IsDhcpInformPacket():
                    self.HandleDhcpInform(packet)
                elif packet.IsDhcpOfferPacket():
                    self.HandleDhcpOffer(packet)
                elif packet.IsDhcpAckPacket():
                    self.HandleDhcpAck(packet)
                elif packet.IsDhcpNackPacket():
                    self.HandleDhcpNack(packet)
                else:
                    self.HandleDhcpUnknown(packet)

                return packet
Beispiel #6
0
        def dhcp_request(self, packet):
            # check to see if lease is still valid, if so: extend lease and send an ACK
            router = ".".join(map(str, packet.GetOption("giaddr")))
            mac = decode_mac(packet.GetOption("chaddr"))
            ciaddr = ".".join(map(str, packet.GetOption("ciaddr")))

            recv_if = packet.get_recv_interface()
            if router == "0.0.0.0":
                if recv_if["broadcast"]:
                    # hey, local DHCP traffic!
                    router = recv_if["address"]

                    # FIXME: If ciaddr is set, we should use a unicast message to client
            requested_ip = bytes_to_ip(packet, "request_ip_address")

            if not requested_ip:
                requested_ip = ciaddr
                if not requested_ip:
                    raise Exception("This really needs fixed...")

            if router == "0.0.0.0" and recv_if["unicast"]:
                # this was a unicast packet, I hope...
                router = requested_ip

            # giaddr = ".".join(map(str, packet.GetOption("giaddr")))

            print("mac: %s, requested address: %s" % (mac, requested_ip))
            # make sure a valid lease exists

            try:
                lease = self.__db.make_dhcp_lease(
                    mac,
                    router,
                    requested_ip,
                    discover=False,
                    server_address=recv_if["address"],
                )
            except error.InvalidIPAddress:
                lease = {
                    "address": None,
                    "error": "address not allowed for client"
                }
            print("got lease: %s" % str(lease))
            if lease["address"] != requested_ip:
                # FIXME: Send a DHCP NAK if authoritative
                print(
                    "Lease invalid... client wants %s, but db gave us %s -- sending NAK"
                    % (requested_ip, lease["address"]))
                nak = dhcp_packet.DhcpPacket()
                # Why use 'NAK' when we can say 'NACK' (which means nothing to me)
                nak.CreateDhcpNackPacketFrom(packet)
                hops = packet.GetOption("hops")
                if hops:
                    nak.SetOption("hops", hops)
                self.SendPacket(nak, giaddr=router)
                return

            ack = dhcp_packet.DhcpPacket()
            ack.CreateDhcpAckPacketFrom(packet)
            # make a list of requested DHCP options
            requested_options = packet.GetOption("parameter_request_list")
            print("requested_options: %s" % requested_options)

            if lease["hostname"] and DhcpOptions[
                    "host_name"] in requested_options:
                ack.SetOption("host_name", list(map(ord, lease["hostname"])))

                # get option/value pairs from database
            opt_vals = self.__db.retrieve_dhcp_options(
                mac=mac, address=requested_ip, option_ids=requested_options)
            print("opt_vals: %s" % str(opt_vals))

            print("Got lease %s from database" % lease)
            # set them on the packet
            # Options to request from the DB (address/gateway are assumed)
            ack.SetOption("yiaddr", ip_to_list(lease["address"]))

            hops = packet.GetOption("hops")
            if hops:
                ack.SetOption("hops", hops)
            ack.SetOption("ip_address_lease_time",
                          int_to_4_bytes(lease["lease_time"]))  # TEST
            ack.SetOption("subnet_mask", ip_to_list(lease["netmask"]))
            ack.SetOption("broadcast_address",
                          ip_to_list(lease["broadcast"]))  # TEST
            ack.SetOption("router", ip_to_list(lease["router"]))

            self.assign_dhcp_options(options=opt_vals,
                                     requested=requested_options,
                                     packet=ack)

            # send an ack
            print("  > sending ack")
            self.SendPacket(ack)

            print(
                "######################################################################"
            )
Beispiel #7
0
        def dhcp_discover(self, packet):
            router = ".".join(map(str, packet.GetOption("giaddr")))
            mac = decode_mac(packet.GetOption("chaddr"))
            requested_ip = bytes_to_ip(packet, "request_ip_address")

            recv_if = packet.get_recv_interface()
            if router == "0.0.0.0":
                if recv_if["broadcast"]:
                    # hey, local DHCP traffic!
                    router = recv_if["address"]

            if not requested_ip:
                requested_ip = "0.0.0.0"

            lease = self.__db.make_dhcp_lease(
                mac,
                router,
                requested_ip,
                discover=True,
                server_address=recv_if["address"],
            )

            print("Got lease %s from database" % lease)

            while self.address_in_use(lease["address"]):
                print("Address %s in use, marking lease %s as abandoned" %
                      (lease["address"], lease))
                dhcp.get_logger().log(
                    dhcp.logging.ERROR,
                    "%-12s Address in use: %(15)s (client: %s)",
                    "ERR/IN_USE:",
                    lease["address"],
                    mac,
                )
                self.__db.mark_abandoned_lease(address=lease["address"])
                lease = self.__db.make_dhcp_lease(
                    mac,
                    router,
                    requested_ip,
                    discover=True,
                    server_address=recv_if["address"],
                )
                print("Got new lease %s from database" % lease)

                # create an offer
            print("> creating offer")
            offer = dhcp_packet.DhcpPacket()
            offer.CreateDhcpOfferPacketFrom(packet)
            hops = packet.GetOption("hops")
            if hops:
                offer.SetOption("hops", hops)

                # fields
                # FIXME: get a free lease from the DB
                # we will need the function to return: the address, the gateway,
                # the network/netmask/broadcast
                # FIXME: what about lease/renewal/rebinding_time, etc?
                # then offer it

                # Options to request from the DB (address/gateway are assumed)
            offer.SetOption("yiaddr", ip_to_list(lease["address"]))

            # options from DB
            print("setting lease time to %s seconds" % lease["lease_time"])
            offer.SetOption("ip_address_lease_time",
                            int_to_4_bytes(lease["lease_time"]))  # TEST
            # offer.SetOption("renewal_time_value",[0,0,0,60]) # TEST
            # offer.SetOption("rebinding_time_value",[0,0,0,105]) # TEST
            offer.SetOption("subnet_mask", ip_to_list(lease["netmask"]))
            offer.SetOption("broadcast_address",
                            ip_to_list(lease["broadcast"]))  # TEST
            offer.SetOption("router", ip_to_list(lease["router"]))

            # offer.SetOption("hops",[1,]) # TEST: number of hops

            # make a list of requested DHCP options
            requested_options = packet.GetOption("parameter_request_list")
            print("requested_options: %s" % requested_options)

            if lease["hostname"] and DhcpOptions[
                    "host_name"] in requested_options:
                offer.SetOption("host_name", list(map(ord, lease["hostname"])))

                # get option/value pairs from database
            opt_vals = self.__db.retrieve_dhcp_options(
                mac=mac, address=requested_ip, option_ids=requested_options)
            print("opt_vals: %s" % str(opt_vals))

            self.assign_dhcp_options(options=opt_vals,
                                     requested=requested_options,
                                     packet=offer)

            # send an offer
            print("  > sending offer")
            self.SendPacket(offer)