//note, the class interface is taken directly from: //http://search.cpan.org/dist/Nmap-Parser/Parser.pm //I even used the same comments in some parts #ifdef WIN32 #define _SECURE_SCL 0 #define _HAS_ITERATOR_DEBUGGING 0 #endif //TODO: add unicode support later #define XML_NO_WIDE_CHAR #include #include #include #include #include #include #include #include #include "xmlParser.h" #ifndef _HNDIFF #define _HNDIFF namespace nmap{ class parser; class nSession { friend class parser; private: //the session variables unsigned int _START_TIME; unsigned int _END_TIME; std::string _START_TIME_ASC; std::string _END_TIME_ASC; std::string _ARGS; std::string _XML_OUT_VER; std::string _VERSION; std::string _SCANNER; public: //Returns the numeric time that the nmap scan finished. const unsigned int finish_time(){ return _END_TIME; } //Returns the version of nmap used for the scan. const std::string nmap_version() { return _VERSION; } //Returns a string which contains the nmap executed command //line used to run the scan. const std::string scan_args() { return _ARGS; } //Returns the human readable format of the start time. const std::string start_str() { return _START_TIME_ASC; } //Returns the numeric form of the time the nmap scan started. const unsigned int start_time() { return _START_TIME; } //Returns the human readable format of the finish time. const std::string finish_str() { return _END_TIME_ASC; } //Returns the version of nmap xml file. const std::string xml_version() { return _XML_OUT_VER; } }; //This object represents the service running on a given port in a given host. //This object is obtained by using the service(protocol, portid) method from //the nHost object. If a portid is given that does not exist on the given host, //these functions will still return an object (so your script doesn't die). //Its good to use tcp_ports() or udp_ports() to see what ports were collected. class nService { friend class parser; friend class nHost; private: std::string _name; std::string _version; std::string _product; std::string _method; unsigned int _port; std::string _proto; int _conf; std::string _extrainfo; std::string _ostype; std::string _tunnel; std::string _fingerprint; public: nService* operator&() { return this; } const bool operator==(nService value); //Returns the port that this service listents on const unsigned int port() { return _port; } //Returns the protocol that this service listens on const std::string proto() { return _proto; } //Returns the service name. const std::string name() { return _name; } //Returns the version of the given product of the running service. const std::string version() { return _version; } //Returns the product information of the service. const std::string product() { return _product; } //Returns the detection method. const std::string method() { return _method; } //Returns the confidence level in service detection. const int confidence() { return _conf; } //Returns any additional information nmap knows about the service. const std::string extrainfo() { return _extrainfo; } //Returns the ostype. (If available) const std::string ostype() { return _ostype; } //Returns the tunnel value. (If available) const std::string tunnel() { return _tunnel; } //Returns the service fingerprint. (If available) const std::string fingerprint() { return _fingerprint; } }; class nHost{ friend class parser; private: //map[proto][port] = nService std::map > _port_service; //map[protocol][state] = port array std::map > > _state_ports; //map[protocol][port] = state std::map > _port_state; //a lit of protocols and states that our ports have std::set _protocols; std::set _states; //map[protocol] = port array std::map > _ports; std::vector _hostnames; std::string _status; std::string _ipv4; std::string _ipv6; std::string _mac; std::string _vendor; std::string _uptime_str; unsigned int _start_time; unsigned int _end_time; unsigned int _uptime_sec; int _distance; public: bool operator ==(nHost value); nHost(); //Returns the time that this host scan began unsigned int scan_start(){ return _start_time; } //Returns the time that this host scan ended unsigned int scan_end(){ return _end_time; } //Returns the state of the host. It is usually one of these (up|down|unknown|skipped). const std::string status() { return _status; } //Returns the main IP address of the host. This is usually the IPv4 address. //If there is no IPv4 address, the IPv6 is returned (hopefully there is one). const std::string addr() { return _ipv4==""?_ipv6:_ipv4; } //Returns the address type of the address given by addr(). const std::string addrtype() { return _ipv4==""?"ipv6":"ipv4"; } //Returns a list of all hostnames found for the given host. const std::vector all_hostnames(){ return _hostnames; } //As a basic call, hostname() returns the first hostname obtained for the given //host. If there exists more than one hostname, you can provide a number, which //is used as the location in the array. The index starts at 0; // //in the case that there are only 2 hostnames //hostname() eq hostname(0); //hostname(1); #second hostname found //hostname(400) eq hostname(1) #nothing at 400; return the name at the last index const std::string hostname(); const std::string hostname(unsigned int index); //Explicitly return the IPv4 address. const std::string ipv4_addr() { return _ipv4; } //Explicitly return the IPv6 address. const std::string ipv6_addr() { return _ipv6; } //Explicitly return the MAC address. const std::string mac_addr() { return _mac; } //Return the vendor information of the MAC. const std::string mac_vendor(){return _vendor;} //Return the distance (in hops) of the target machine from the machine that //performed the scan. const int distance() {return _distance;} //Returns the human readable format of the timestamp of when the host had last rebooted. const std::string uptime_lastboot() { return _uptime_str; } //Returns the number of seconds that have passed since the host's last boot from when the scan was performed. const unsigned int uptime_seconds() { return _uptime_sec; } //Returns a list of all possible protocols in this host const std::set protocols() { return _protocols; } //Returns a list of all possible states in this host const std::set states() { return _states; } //Returns the sorted list of TCP|UDP ports respectively that were scanned on this host. //Optionally a string argument can be given to these functions to filter the list. //tcp_ports("open") // returns all only 'open' ports (not 'open|filtered') // //udp_ports("open|filtered"); // matches exactly ports with 'open|filtered' but not 'open' const std::vector ports(std::string proto); const std::vector ports(std::string proto, std::string states); //Returns the total of TCP|UDP ports scanned respectively. const unsigned int port_count(std::string proto) { return _ports[proto].size(); } //Returns the state of the given port, provided by the port number in portID. const std::string port_state(std::string proto, unsigned int portID) { return _port_state[proto][portID]; } //Returns the Nmap::Parser::Host::Service object of a given service running on port, provided by $portid. See Nmap::Parser::Host::Service for more info. //svc = host.service("tcp", 80); //svc.name; //svc.proto; nService service(std::string proto, unsigned int portid) { return _port_service[proto][portid]; } //TODO: I will have to implement these a later // string os_sig(); // // Returns an Nmap::Parser::Host::OS object that can be used to obtain all the Operating System signature (fingerprint) information. See Nmap::Parser::Host::OS for more details. // // $os = $host->os_sig; // $os->name; // $os->osfamily; // // // Returns the list of closed TCP|UDP ports respectively. Note that if a port state is for example, 'closed|filtered', it will appear on this list as well. }; //this class represents one nmap xml file - all the data in it class parser{ public: nSession Session; ~parser(); parser(){} parser(std::string filename); void setfile(std::string filename); //Deallocs all dynamic variables. void purge(); //Obtains the Nmap::Parser::Host object for the given ip_addr. nHost* get_host(std::string ip_addr); //Returns an array of all the Nmap::Parser::Host objects for the scan. //If the optional status is given, it will only return those hosts that match that status. //The status can be any of the following: (up|down|unknown|skipped) const std::vector all_hosts(); const std::vector all_hosts(std::string status); //return a set of all possible statuses const std::set status(); //Returns the list of IP addresses that were scanned in this nmap session. // If the optional status is given, it will only return those IP addresses //that match that status. The status can be any of the following: //(up|down|unknown|skipped) const std::vector get_ips(); const std::vector get_ips(std::string status); private: //parse functions //TODO: these functions need a major facelift //I just wanted to get htem done quick, so I could focus on libndiff void parse(); void parse_nmaprun(XMLNode &pointer); void parse_scaninfo(XMLNode &pointer); void parse_host(const XMLNode &pointer); void parse_host_state(const XMLNode &pointer, nHost &tmpHost); void parse_host_address(const XMLNode &pointer, nHost &tmpHost); void parse_host_names(const XMLNode &pointer, nHost &tmpHost); void parse_host_ports(const XMLNode &pointer, nHost &tmpHost); int parse_host_ports_service(const XMLNode &pointer, nService &serv); int parse_host_ports_chidren(const XMLNode &pointer, std::string &pstate, nService &serv); //end std::map _IP_Host; std::map > _State_Hosts; std::map > _State_IPs; std::set _states; std::vector _Hosts; //the root xml node XMLNode r_xmlNode; }; } #endif