def try_password(options, password, output=None, k=0):

    p = SAPRouter(type=SAPRouter.SAPROUTER_ADMIN,
                  version=options.router_version)
    p.adm_command = 2
    p.adm_password = password
    p = str(SAPNI() / p)

    import fau_timer
    fau_timer.init()
    fau_timer.send_request(options.remote_host, options.remote_port, p, len(p))
    fau_timer.calculate_time()
    cpuSpeed = fau_timer.get_speed()
    cpuTicks = fau_timer.get_cpu_ticks()
    time = fau_timer.get_time()

    if options.verbose:
        print("Request time: CPU Speed: %s Hz CPU Ticks: %s Time: %s nanosec" %
              (cpuSpeed, cpuTicks, time))

    # Write the time to the output file
    if output:
        output.write("%i,%s,%s\n" % (k, password, time))

    return time
    def test_saprouter_route_dissection(self):
        """Test dissection of a SAP Router route request."""

        # Build the Route request packet
        router_string = [SAPRouterRouteHop(hostname="1.2.3.4",
                                           port=1234),
                         SAPRouterRouteHop(hostname="4.3.2.1",
                                           port=4321,
                                           password="******")]
        router_string_lens = list(map(len, list(map(str, router_string))))
        p = SAPRouter(type=SAPRouter.SAPROUTER_ROUTE,
                      route_entries=len(router_string),
                      route_talk_mode=1,
                      route_rest_nodes=1,
                      route_length=sum(router_string_lens),
                      route_offset=router_string_lens[0],
                      route_string=router_string)

        pkt = Ether()/IP()/TCP(sport=3299, dport=9999)/SAPNI()/p

        packet = self.get_capture(pkt)[0]

        self.assertIn('sapni', packet)
        self.assertEqual(int(packet['sapni'].length), len(p))
        self.assertIn('saprouter', packet)
        self.assert_fields(p, packet["saprouter"], self.route_mapping)
        self.assertEqual("Route password found", packet['saprouter']._ws_expert_message)
def get_router_version(connection):
    r = connection.sr(
        SAPRouter(type=SAPRouter.SAPROUTER_CONTROL, version=40, opcode=1))
    if router_is_control(r) and r.opcode == 2:
        return r.version
    else:
        return None
    def test_saprouter_dissection(self):
        """Test dissection of a basic SAP Router packet. """
        pkt = Ether() / IP() / TCP(dport=3299) / SAPNI() / SAPRouter()

        packet = self.get_capture(pkt)[0]

        self.assertIn('sapni', packet)
        self.assertEqual(int(packet['sapni'].length), 24)
        self.assertIn('saprouter', packet)
Exemple #5
0
    def handle_data(self):
        if self.routed:
            self.request.send(self.packet)
            return

        self.packet.decode_payload_as(SAPRouter)
        route_request = self.packet[SAPRouter]

        if router_is_route(route_request):
            if route_request.route_string[1].hostname == "10.0.0.1" and \
               route_request.route_string[1].port == "3200":
                self.routed = True
                self.request.send(SAPRouter(type=SAPRouter.SAPROUTER_PONG))
            else:
                self.request.send(SAPRouter(type=SAPRouter.SAPROUTER_ERROR,
                                            return_code=-94))
        else:
            self.request.send(SAPRouter(type=SAPRouter.SAPROUTER_ERROR))
Exemple #6
0
    def route(self, server):
        print "[*] Routing to %s:%d !" % (self.options.target_host,
                                          self.options.target_port)

        # Build the Route request packet
        router_string = [SAPRouterRouteHop(hostname=self.options.remote_host,
                                           port=self.options.remote_port),
                         SAPRouterRouteHop(hostname=self.options.target_host,
                                           port=self.options.target_port,
                                           password=self.options.target_pass)]
        router_string_lens = map(len, map(str, router_string))
        p = SAPRouter(type=SAPRouter.SAPROUTER_ROUTE,
                      route_entries=len(router_string),
                      route_talk_mode=1,
                      route_rest_nodes=1,
                      route_length=sum(router_string_lens),
                      route_offset=router_string_lens[0],
                      route_string=router_string)

        if self.options.verbose:
            p.show2()

        # Send the request and grab the response
        response = server.sr(p)

        if SAPRouter in response:
            response = response[SAPRouter]
            if router_is_pong(response):
                print "[*] Route request accepted !"
                self.routed = True
            elif router_is_error(response) and response.return_code == -94:
                print "[*] Route request not accepted !"
                print response.err_text_value
                raise RouteException("Route request not accepted")
            else:
                print "[*] Router send error"
                print response.err_text_value
                raise Exception("Router error: %s", response.err_text_value)
        else:
            print "[*] Wrong response received !"
            raise Exception("Wrong response received")
Exemple #7
0
def try_password(options, password, output=None, k=0):

    p = SAPRouter(type=SAPRouter.SAPROUTER_ADMIN, version=options.router_version)
    p.adm_command = 2
    p.adm_password = password
    p = str(SAPNI() / p)

    fau_timer.init()
    fau_timer.send_request(options.remote_host, options.remote_port, p, len(p))
    fau_timer.calculate_time()
    cpu_peed = fau_timer.get_speed()
    cpu_ticks = fau_timer.get_cpu_ticks()
    time = fau_timer.get_time()

    if options.verbose:
        print("Request time: CPU Speed: %s Hz CPU Ticks: %s Time: %s nanosec" % (cpu_peed, cpu_ticks, time))

    # Write the time to the output file
    if output:
        output.write("%i,%s,%s\n" % (k, password, time))

    return time
    def test_saprouter_admin_peer_trace_dissection(self):
        """Test dissection of a SAP Router admin set/clear peer trace."""

        for command in [10, 11]:
            # Build the Admin packet
            p = SAPRouter(type=SAPRouter.SAPROUTER_ADMIN,
                          version=2,
                          adm_command=command,
                          adm_address_mask="0.0.0.0")

            pkt = Ether()/IP()/TCP(sport=3299, dport=9999)/SAPNI()/p

            packet = self.get_capture(pkt)[0]

            self.assertIn('sapni', packet)
            self.assertEqual(int(packet['sapni'].length), len(p))
            self.assertIn('saprouter', packet)
            self.assert_fields(p, packet["saprouter"], self.admin_mapping)
    def test_saprouter_admin_info_request_dissection(self):
        """Test dissection of a SAP Router admin info request."""

        # Build the Admin packet
        p = SAPRouter(type=SAPRouter.SAPROUTER_ADMIN,
                      version=2,
                      adm_command=2,
                      adm_password="******")

        pkt = Ether()/IP()/TCP(sport=3299, dport=9999)/SAPNI()/p

        packet = self.get_capture(pkt)[0]

        self.assertIn('sapni', packet)
        self.assertEqual(int(packet['sapni'].length), len(p))
        self.assertIn('saprouter', packet)
        self.assert_fields(p, packet["saprouter"], self.admin_mapping)
        self.assertEqual("Info password found", packet['saprouter']._ws_expert_message)
    def test_saprouter_admin_cancel_trace_route_dissection(self):
        """Test dissection of a SAP Router admin cancel route and trace route request."""

        for command in [6, 12, 13]:
            # Build the Admin packet
            p = SAPRouter(type=SAPRouter.SAPROUTER_ADMIN,
                          version=2,
                          adm_command=command,
                          adm_client_count=2,
                          adm_client_ids=[1,2])

            pkt = Ether()/IP()/TCP(sport=3299, dport=9999)/SAPNI()/p

            packet = self.get_capture(pkt)[0]

            self.assertIn('sapni', packet)
            self.assertEqual(int(packet['sapni'].length), len(p))
            self.assertIn('saprouter', packet)
            self.assert_fields(p, packet["saprouter"], self.admin_mapping)
Exemple #11
0
 def handle_control(self, pkt):
     """Handles control messages"""
     opcode_str = router_control_opcodes[pkt.opcode] if pkt.opcode in router_control_opcodes else "unknown"
     self.logger.debug("Handling control message, opcode %d (%s)",
                       pkt.opcode, opcode_str)
     # Version request
     if pkt.opcode == 1:
         self.logger.debug("Received version request (client version %d)", pkt.version)
         self.server.clients[self.client_address].ni_version = pkt.version
         self.request.send(SAPRouter(type=SAPRouter.SAPROUTER_CONTROL,
                                     version=self.router_version,
                                     opcode=2,
                                     return_code=-13))
     else:
         self.logger.debug("Unhandled opcode %d (%s)",
                           pkt.opcode, opcode_str)
         return self.return_error(return_code=-13,
                                  error="invalid client version",
                                  detail="NiBufIProcMsg: unknown opcode 3 received")
    def test_saprouter_control_dissection(self):
        """Test dissection of a SAP Router control."""

        # Build the Control packet
        p = SAPRouter(type=SAPRouter.SAPROUTER_CONTROL,
                      version=2,
                      opcode=1,
                      return_code=-99,
                      control_text_length=8,
                      control_text_value="SOMEDATA")

        pkt = Ether()/IP()/TCP(sport=3299, dport=9999)/SAPNI()/p

        packet = self.get_capture(pkt)[0]

        self.assertIn('sapni', packet)
        self.assertEqual(int(packet['sapni'].length), len(p))
        self.assertIn('saprouter', packet)
        self.assert_fields(p, packet["saprouter"], self.control_mapping)
Exemple #13
0
    def return_error(self, **options):
        """Returns an error response"""
        self.logger.debug("Returning error code %d (%s)", options.get("return_code"),
                          router_return_codes[options.get("return_code")])

        error_text = SAPRouterError(release=str(self.release),
                                    version=str(self.router_version),
                                    error_time=datetime.now().strftime(SAPRouterError.time_format),
                                    location="SAPRouter %d.%d on '%s'" % (self.router_version,
                                                                          self.router_version_patch,
                                                                          self.hostname))
        for field in list(options.keys()):
            setattr(error_text, field, options[field])

        error_pkt = SAPRouter(type=SAPRouter.SAPROUTER_ERROR,
                              version=self.router_version,
                              opcode=0,
                              return_code=options.get("return_code"),
                              err_text_value=error_text)
        self.request.send(error_pkt)
        self.session.add_event("Returned error",
                               data={"return_code": options.get("return_code"),
                                     "error_msg": router_return_codes[options.get("return_code")]},
                               response=str(error_pkt))
Exemple #14
0
def main():
    options = parse_options()

    if options.verbose:
        logging.basicConfig(level=logging.DEBUG)

    response = False

    p = SAPRouter(type=SAPRouter.SAPROUTER_ADMIN)

    if options.stop:
        p.adm_command = 5
        print "[*] Requesting stop of the remote SAP Router"

    elif options.soft:
        p.adm_command = 9
        print "[*] Requesting a soft shutdown of the remote SAP Router"
        response = True

    elif options.info:
        p.adm_command = 2
        if options.info_password:
            if len(options.info_password) > 19:
                print "[*] Password too long, truncated at 19 characters"
            p.adm_password = options.info_password
            print "[*] Requesting info using password", p.adm_password
        else:
            print "[*] Requesting info"
        response = True

    elif options.new_route:
        p.adm_command = 3
        print "[*] Requesting a refresh of the router table"

    elif options.trace:
        p.adm_command = 4
        print "[*] Requesting a toggle on the trace settings"

    elif options.cancel:
        p.adm_command = 6
        p.adm_client_ids = map(int, options.cancel.split(","))
        print "[*] Requesting a cancel of the route(s) with client id(s) %s" % p.adm_client_ids
        response = True

    elif options.dump:
        p.adm_command = 7
        print "[*] Requesting a dump of the buffers"

    elif options.flush:
        p.adm_command = 8
        print "[*] Requesting a flush of the buffers"

    elif options.hide:
        p.adm_command = 14
        print "[*] Requesting a hide on the errors to clients"
        response = True

    elif options.set_peer:
        p.adm_command = 10
        p.adm_address_mask = options.set_peer
        print "[*] Request a set peer trace for the address mask %s" % p.adm_address_mask
        response = True

    elif options.clear_peer:
        p.adm_command = 11
        p.adm_address_mask = options.clear_peer
        print "[*] Request a clear peer trace for the address mask %s" % p.adm_address_mask
        response = True

    elif options.trace_conn:
        p.adm_command = 12
        p.adm_client_ids = map(int, options.trace_conn.split(","))
        print "[*] Requesting a connection trace with client id(s) %s" % p.adm_client_ids
        response = True

    else:
        print "[*] No command specified !"
        return

    # Initiate the connection
    conn = SAPNIStreamSocket.get_nisocket(options.remote_host, options.remote_port)
    print "[*] Connected to the SAP Router %s:%d" % (options.remote_host, options.remote_port)

    # Retrieve the router version used by the server if not specified
    if options.router_version:
        p.version = options.router_version
    else:
        p.version = get_router_version(conn) or p.version
    print "[*] Using SAP Router version %d" % p.version

    # Send the router admin request
    print "[*] Sending Router Admin packet"
    if options.verbose:
        p.show2()
    conn.send(p)

    # Grab the response if required
    if response:

        # Some responses has no SAPRouter's packet format and are raw strings,
        # we need to get the SAP NI layer first and then check if we could go
        # down to the SAPRouter layer.
        response = conn.recv()[SAPNI]
        if SAPRouter in response and response[SAPRouter].payload:
            response = response[SAPRouter]

        # If the response is an error, print and exit
        if router_is_error(response):
            print "[*] Error requesting info:"
            if options.verbose:
                response.show2()
            else:
                print response.err_text_value

        # Otherwise, print all the packets sent by the SAP Router
        else:
            print "[*] Response:"
            try:
                while (response):
                    print response.payload
                    response = conn.recv()
            except:
                pass
Exemple #15
0
def main():
    options = parse_options()

    if options.verbose:
        logging.basicConfig(level=logging.DEBUG)

    response = False

    p = SAPRouter(type=SAPRouter.SAPROUTER_ADMIN)

    if options.stop:
        p.adm_command = 5
        print("[*] Requesting stop of the remote SAP Router")

    elif options.soft:
        p.adm_command = 9
        print("[*] Requesting a soft shutdown of the remote SAP Router")
        response = True

    elif options.info:
        p.adm_command = 2
        if options.info_password:
            if len(options.info_password) > 19:
                print("[*] Password too long, truncated at 19 characters")
            p.adm_password = options.info_password
            print("[*] Requesting info using password %s" % p.adm_password)
        else:
            print("[*] Requesting info")
        response = True

    elif options.new_route:
        p.adm_command = 3
        print("[*] Requesting a refresh of the router table")

    elif options.trace:
        p.adm_command = 4
        print("[*] Requesting a toggle on the trace settings")

    elif options.cancel:
        p.adm_command = 6
        p.adm_client_ids = list(map(int, options.cancel.split(",")))
        print("[*] Requesting a cancel of the route(s) with client id(s) %s" %
              p.adm_client_ids)
        response = True

    elif options.dump:
        p.adm_command = 7
        print("[*] Requesting a dump of the buffers")

    elif options.flush:
        p.adm_command = 8
        print("[*] Requesting a flush of the buffers")

    elif options.hide:
        p.adm_command = 14
        print("[*] Requesting a hide on the errors to clients")
        response = True

    elif options.set_peer:
        p.adm_command = 10
        p.adm_address_mask = options.set_peer
        print("[*] Request a set peer trace for the address mask %s" %
              p.adm_address_mask)
        response = True

    elif options.clear_peer:
        p.adm_command = 11
        p.adm_address_mask = options.clear_peer
        print("[*] Request a clear peer trace for the address mask %s" %
              p.adm_address_mask)
        response = True

    elif options.trace_conn:
        p.adm_command = 12
        p.adm_client_ids = list(map(int, options.trace_conn.split(",")))
        print("[*] Requesting a connection trace with client id(s) %s" %
              p.adm_client_ids)
        response = True

    else:
        print("[*] No command specified !")
        return

    # Initiate the connection
    conn = SAPNIStreamSocket.get_nisocket(options.remote_host,
                                          options.remote_port)
    print("[*] Connected to the SAP Router %s:%d" %
          (options.remote_host, options.remote_port))

    # Retrieve the router version used by the server if not specified
    if options.router_version:
        p.version = options.router_version
    else:
        p.version = get_router_version(conn) or p.version
    print("[*] Using SAP Router version %d" % p.version)

    # Send the router admin request
    print("[*] Sending Router Admin packet")
    if options.verbose:
        p.show2()
    conn.send(p)

    # Grab the response if required
    if response:

        # Some responses has no SAPRouter's packet format and are raw strings,
        # we need to get the SAP NI layer first and then check if we could go
        # down to the SAPRouter layer.
        raw_response = conn.recv()[SAPNI]
        if SAPRouter in raw_response:
            router_response = raw_response[SAPRouter]

        # If the response was null, just return
        elif raw_response.length == 0:
            return

        # If the response is an error, print and exit
        if router_is_error(router_response):
            print("[*] Error requesting info:")
            if options.verbose:
                router_response.show2()
            else:
                print(router_response.err_text_value.error)

        # Otherwise, print the packets sent by the SAP Router
        else:
            print("[*] Response:\n")

            if options.info:
                # Decode the first packet as a list of info client
                raw_response.decode_payload_as(SAPRouterInfoClients)

                clients = []
                clients.append("\t".join(
                    ["ID", "Client", "Partner", "Service", "Connected on"]))
                clients.append("-" * 60)
                for client in raw_response.clients:

                    # If the trace flag is set, add a mark
                    flag = "(*)" if client.flag_traced else "(+)" if client.flag_routed else ""

                    fields = [
                        str(client.id), client.address,
                        "%s%s" % (flag, client.partner)
                        if client.flag_routed else "(no partner)",
                        client.service if client.flag_routed else "",
                        datetime.fromtimestamp(client.connected_on).ctime()
                    ]
                    clients.append("\t".join(fields))

                # Decode the second packet as server info
                raw_response = conn.recv()
                raw_response.decode_payload_as(SAPRouterInfoServer)

                print(
                    "SAP Network Interface Router running on port %d (PID = %d)\n"
                    "Started on: %s\n"
                    "Parent process: PID = %d, port = %d\n" %
                    (raw_response.port, raw_response.pid,
                     datetime.fromtimestamp(raw_response.started_on).ctime(),
                     raw_response.ppid, raw_response.pport))

                print("\n".join(clients))
                print("(*) Connections being traced")

            # Show the plain packets returned
            try:
                raw_response = conn.recv()
                while raw_response:
                    print(raw_response.payload)
                    raw_response = conn.recv()
            except error:
                pass
Exemple #16
0

# The fields used to identify a version being fingerprinted
version_info_fields = ["version", "release", "patch_number", "source_id", "update_level", "file_version", "platform",
                       "submitted_by", "comment"]


# This is the list of target packets that we use during the fingerprinting. Basically it consist of a dict with the
# key being the name of the target packet and the value the construction of it.
fingerprint_targets = {
    # Connect to the SAP Route but not send any packet to trigger a timeout
    "Timeout": None,
    # Send a large packet
    "Network packet too big": Raw("X" * 10025),
    # Use an invalid opcode
    "Invalid control opcode": SAPRouter(type=SAPRouter.SAPROUTER_CONTROL, version=38, opcode=3),
    # Do not send a route
    "No route": SAPRouter(type=SAPRouter.SAPROUTER_ROUTE),
    # Set one entry but do no provide a route
    "No route one entry": SAPRouter(type=SAPRouter.SAPROUTER_ROUTE,
                                    route_entries=1),
    # Set one entry with an invalid length but do no provide it
    "No route invalid length": SAPRouter(type=SAPRouter.SAPROUTER_ROUTE,
                                         route_entries=2,
                                         route_rest_nodes=1,
                                         route_length=1,
                                         route_offset=3),
    # Set one entry with an invalid route
    "Empty route invalid length": SAPRouter(type=SAPRouter.SAPROUTER_ROUTE,
                                            route_entries=2,
                                            route_rest_nodes=1,
Exemple #17
0
    "version", "release", "patch_number", "source_id", "update_level",
    "file_version", "platform", "submitted_by", "comment"
]

# This is the list of target packets that we use during the fingerprinting. Basically it consist of a dict with the
# key being the name of the target packet and the value the construction of it.
fingerprint_targets = {
    # Connect to the SAP Route but not send any packet to trigger a timeout
    "Timeout":
    None,
    # Send a large packet
    "Network packet too big":
    Raw("X" * 10025),
    # Use an invalid opcode
    "Invalid control opcode":
    SAPRouter(type=SAPRouter.SAPROUTER_CONTROL, version=38, opcode=3),
    # Do not send a route
    "No route":
    SAPRouter(type=SAPRouter.SAPROUTER_ROUTE),
    # Set one entry but do no provide a route
    "No route one entry":
    SAPRouter(type=SAPRouter.SAPROUTER_ROUTE, route_entries=1),
    # Set one entry with an invalid length but do no provide it
    "No route invalid length":
    SAPRouter(type=SAPRouter.SAPROUTER_ROUTE,
              route_entries=2,
              route_rest_nodes=1,
              route_length=1,
              route_offset=3),
    # Set one entry with an invalid route
    "Empty route invalid length":
Exemple #18
0
    def route_request(self, pkt):
        """Perform a lookup on the route table and routes the packet accordingly
        if allowed.
        """
        route_string = pkt.route_string[pkt.route_rest_nodes]
        (action, talk_mode, password) = self.server.route_table.lookup_target(route_string.hostname,
                                                                              int(route_string.port))

        if action == RouteTable.ROUTE_DENY:
            self.logger.debug("Route to %s:%s denied" % (route_string.hostname,
                                                         route_string.port))
            self.return_error(return_code=-94,
                              error="%s: route permission denied (%s to %s, %s)" % (self.hostname,
                                                                                    self.server.listener_address,
                                                                                    route_string.hostname,
                                                                                    route_string.port))
            return

        elif talk_mode != RouteTable.MODE_ANY and talk_mode != pkt.route_talk_mode:
            self.logger.debug("Talk mode (%d) to %s:%s denied" % (pkt.route_talk_mode,
                                                                  route_string.hostname,
                                                                  route_string.port))
            self.return_error(return_code=2)  # TODO: Return the proper error
            return

        elif action == RouteTable.ROUTE_ALLOW:
            if password:
                if password == route_string.password:
                    self.logger.debug("Valid password for route to %s:%s" % (route_string.hostname,
                                                                             route_string.port))
                    self.session.add_event("Route request allowed, valid password", data={"target_host": route_string.hostname,
                                                                                          "target_port": route_string.port,
                                                                                          "password": route_string.password},
                                           request=str(pkt))

                else:
                    self.logger.debug("Invalid password for route to %s:%s" % (route_string.hostname,
                                                                               route_string.port))
                    self.session.add_event("Route request allowed, invalid password", data={"target_host": route_string.hostname,
                                                                                            "target_port": route_string.port,
                                                                                            "password": route_string.password},
                                           request=str(pkt))
                    self.return_error(return_code=3)  # TODO: Return the proper error
                    return

            else:
                self.logger.debug("Route request allowed to %s:%s" % (route_string.hostname,
                                                                      route_string.port))
                self.session.add_event("Route request allowed", data={"target": route_string.hostname,
                                                                      "port": route_string.port,
                                                                      "password": route_string.password},
                                       request=str(pkt))

        # The route is accepted, now look the service for the target address/port
        # and register it as routed
        service = self.server.service_manager.find_service_by_address(route_string.hostname,
                                                                      int(route_string.port))

        # If the service wasn't found, we should return a timeout message,
        # meaning that the SAP Router tried to connect to the target service
        # but it didn't responded
        if service is None:
            self.logger.debug("Target service %s:%s not available" % (route_string.hostname,
                                                                      route_string.port))
            self.session.add_event("Target service not available", data={"target": route_string.hostname,
                                                                         "port": route_string.port,
                                                                         "password": route_string.password},
                                   request=str(pkt))

        else:
            self.logger.debug("Target service %s:%s found, registering and routing" % (route_string.hostname,
                                                                                       route_string.port))

            # First cancel the timeout as a valid route was specified
            self._timeout.cancel()

            # Register the current client as routed and set the target
            # address, port and service
            self.server.clients[self.client_address].routed = True
            self.server.clients[self.client_address].connected = True
            self.server.clients[self.client_address].target_service = service
            self.server.clients[self.client_address].talk_mode = pkt.route_talk_mode
            self.server.clients[self.client_address].partner = route_string.hostname
            self.server.clients[self.client_address].service = int(route_string.port)

            # Send a PONG message to notify the client the route was accepted
            self.request.send(SAPRouter(type=SAPRouter.SAPROUTER_PONG))
Exemple #19
0
def main():
    options = parse_options()

    if options.verbose:
        logging.basicConfig(level=logging.DEBUG)

    response = False

    p = SAPRouter(type=SAPRouter.SAPROUTER_ADMIN)

    if options.stop:
        p.adm_command = 5
        print("[*] Requesting stop of the remote SAP Router")

    elif options.soft:
        p.adm_command = 9
        print("[*] Requesting a soft shutdown of the remote SAP Router")
        response = True

    elif options.info:
        p.adm_command = 2
        if options.info_password:
            if len(options.info_password) > 19:
                print("[*] Password too long, truncated at 19 characters")
            p.adm_password = options.info_password
            print("[*] Requesting info using password %s" % p.adm_password)
        else:
            print("[*] Requesting info")
        response = True

    elif options.new_route:
        p.adm_command = 3
        print("[*] Requesting a refresh of the router table")

    elif options.trace:
        p.adm_command = 4
        print("[*] Requesting a toggle on the trace settings")

    elif options.cancel:
        p.adm_command = 6
        p.adm_client_ids = list(map(int, options.cancel.split(",")))
        print("[*] Requesting a cancel of the route(s) with client id(s) %s" % p.adm_client_ids)
        response = True

    elif options.dump:
        p.adm_command = 7
        print("[*] Requesting a dump of the buffers")

    elif options.flush:
        p.adm_command = 8
        print("[*] Requesting a flush of the buffers")

    elif options.hide:
        p.adm_command = 14
        print("[*] Requesting a hide on the errors to clients")
        response = True

    elif options.set_peer:
        p.adm_command = 10
        p.adm_address_mask = options.set_peer
        print("[*] Request a set peer trace for the address mask %s" % p.adm_address_mask)
        response = True

    elif options.clear_peer:
        p.adm_command = 11
        p.adm_address_mask = options.clear_peer
        print("[*] Request a clear peer trace for the address mask %s" % p.adm_address_mask)
        response = True

    elif options.trace_conn:
        p.adm_command = 12
        p.adm_client_ids = list(map(int, options.trace_conn.split(",")))
        print("[*] Requesting a connection trace with client id(s) %s" % p.adm_client_ids)
        response = True

    else:
        print("[*] No command specified !")
        return

    # Initiate the connection
    conn = SAPNIStreamSocket.get_nisocket(options.remote_host, options.remote_port)
    print("[*] Connected to the SAP Router %s:%d" % (options.remote_host, options.remote_port))

    # Retrieve the router version used by the server if not specified
    if options.router_version:
        p.version = options.router_version
    else:
        p.version = get_router_version(conn) or p.version
    print("[*] Using SAP Router version %d" % p.version)

    # Send the router admin request
    print("[*] Sending Router Admin packet")
    if options.verbose:
        p.show2()
    conn.send(p)

    # Grab the response if required
    if response:

        # Some responses has no SAPRouter's packet format and are raw strings,
        # we need to get the SAP NI layer first and then check if we could go
        # down to the SAPRouter layer.
        raw_response = conn.recv()[SAPNI]
        if SAPRouter in raw_response:
            router_response = raw_response[SAPRouter]

        # If the response was null, just return
        elif raw_response.length == 0:
            return

        # If the response is an error, print and exit
        if router_is_error(router_response):
            print("[*] Error requesting info:")
            if options.verbose:
                router_response.show2()
            else:
                print(router_response.err_text_value.error)

        # Otherwise, print the packets sent by the SAP Router
        else:
            print("[*] Response:\n")

            if options.info:
                # Decode the first packet as a list of info client
                raw_response.decode_payload_as(SAPRouterInfoClients)

                clients = []
                clients.append("\t".join(["ID", "Client", "Partner", "Service", "Connected on"]))
                clients.append("-" * 60)
                for client in raw_response.clients:

                    # If the trace flag is set, add a mark
                    flag = "(*)" if client.flag_traced else "(+)" if client.flag_routed else ""

                    fields = [str(client.id),
                              client.address,
                              "%s%s" % (flag, client.partner) if client.flag_routed else "(no partner)",
                              client.service if client.flag_routed else "",
                              datetime.fromtimestamp(client.connected_on).ctime()]
                    clients.append("\t".join(fields))

                # Decode the second packet as server info
                raw_response = conn.recv()
                raw_response.decode_payload_as(SAPRouterInfoServer)

                print("SAP Network Interface Router running on port %d (PID = %d)\n"
                      "Started on: %s\n"
                      "Parent process: PID = %d, port = %d\n" % (raw_response.port, raw_response.pid,
                                                                 datetime.fromtimestamp(raw_response.started_on).ctime(),
                                                                 raw_response.ppid, raw_response.pport))

                print("\n".join(clients))
                print("(*) Connections being traced")

            # Show the plain packets returned
            try:
                raw_response = conn.recv()
                while raw_response:
                    print(raw_response.payload)
                    raw_response = conn.recv()
            except error:
                pass