#include "libndiff.h" using namespace std; using namespace nmap; void libndiff::_init_xml(){ _xml_node = XMLNode::createXMLTopNode("xml",TRUE); _xml_node.addAttribute("version","1.0"); //TODO: add nmap.dtd } void libndiff::_add_scan(XMLNode &root, string start, string end){ _simple << _old_scan.Session.start_str() << " -> " << _new_scan.Session.start_str() << endl; root = _xml_node.addChild("scandiff"); root.addAttribute("startdate", _old_scan.Session.start_str().c_str()); root.addAttribute("enddate", _new_scan.Session.start_str().c_str()); } void libndiff::_add_host_up(XMLNode &parent, XMLNode &child, nHost &host){ XMLNode addrnode; child = parent.addChild("addhost"); addrnode = child.addChild("address"); addrnode.addAttribute("addr",host.addr().c_str()); addrnode.addAttribute("addrtype",host.addrtype().c_str()); _simple << host.addr(); if(displayHosts && host.hostname()!=""){ _simple << " (" << host.hostname() << ")"; } _simple << ":" << endl; _simple << "\t Host has come online." << endl; } void libndiff::_add_host_down(XMLNode &parent, XMLNode &child, nHost &host){ XMLNode addrnode; child = parent.addChild("delhost"); addrnode = child.addChild("address"); addrnode.addAttribute("addr",host.addr().c_str()); addrnode.addAttribute("addrtype",host.addrtype().c_str()); _simple << host.addr(); if(displayHosts && host.hostname()!=""){ _simple << " (" << host.hostname() << ")"; } _simple << ":" << endl; _simple << "\t Host has gone offline." << endl; } void libndiff::_add_host_chg(XMLNode &parent, XMLNode &child, nHost &host){ XMLNode addrnode; child = parent.addChild("chghost"); addrnode = child.addChild("address"); addrnode.addAttribute("addr",host.addr().c_str()); addrnode.addAttribute("addrtype",host.addrtype().c_str()); _simple << host.addr(); if(displayHosts && host.hostname()!=""){ _simple << " (" << host.hostname() << ")"; } _simple << ":" << endl; } //for extra addresses void libndiff::_add_addr(XMLNode &parent, string addr, string addrtype, string vendor){ XMLNode addrnode; addrnode=parent.addChild("address"); addrnode.addAttribute("addr",addr.c_str()); addrnode.addAttribute("addrtype",addrtype.c_str()); if(vendor!=""){ addrnode.addAttribute("vendor",vendor.c_str()); } } void libndiff::_add_port(XMLNode &parent, string proto, unsigned int port, string oldState, string newState){ XMLNode child; ostringstream iss; string port_s; iss << port; port_s = iss.str(); child =parent.addChild("port"); child.addAttribute("protocol",proto.c_str()); child.addAttribute("portid",port_s.c_str()); _simple << "\t Port " << port << "/" << proto; if(oldState != ""){ XMLNode oldS =child.addChild("delstate"); oldS.addAttribute("state", oldState.c_str()); _simple << " was " << oldState; } if(newState != ""){ XMLNode newS =child.addChild("addstate"); newS.addAttribute("state", newState.c_str()); _simple << " is now " << newState; } _simple << endl; } void libndiff::_add_service(XMLNode &parent, nService *oldService, nService *newService){ if(newService!=NULL){ XMLNode servnode =parent.addChild("addservice"); servnode.addAttribute("name", newService->name().c_str()); servnode.addAttribute("product", newService->product().c_str()); servnode.addAttribute("version", newService->version().c_str()); servnode.addAttribute("method", newService->method().c_str()); _simple << "\t Port " << newService->port() << "/" << newService->proto() << " is now listening with " << newService->product() << " " << newService->version() << endl; } if(oldService!=NULL){ XMLNode servnode =parent.addChild("delservice"); servnode.addAttribute("name", oldService->name().c_str()); servnode.addAttribute("product", oldService->product().c_str()); servnode.addAttribute("version", oldService->version().c_str()); servnode.addAttribute("method", oldService->method().c_str()); _simple << "\t Port " << oldService->port() << "/" << oldService->proto() << " was listening with " << oldService->product() << " " << oldService->version() << endl; } } void libndiff::_addhost(XMLNode &root){ for(vector::iterator ho=_up_hosts.begin(); ho!=_up_hosts.end(); ho++){ XMLNode parent; _add_host_up(root, parent, *ho); if(ho->addrtype()=="ipv4"){ if(ho->ipv6_addr()!=""){ _add_addr(parent,ho->ipv6_addr(),"ipv6",""); } if(ho->mac_addr()!=""){ _add_addr(parent,ho->mac_addr(),"mac",ho->mac_vendor()); } } set proto = ho->protocols(); for(set::iterator it=proto.begin(); it!=proto.end(); it++){ vector ports = ho->ports(*it); for(vector::iterator po = ports.begin(); po!=ports.end(); po++){ _add_port(parent,*it,*po,"",ho->port_state(*it, *po)); //print any service state changes if(ho->service(*it,*po).product() !=""){ _add_service(parent,NULL,&ho->service(*it,*po)); } } } } } void libndiff::_chghost(XMLNode &root){ for(vector >::iterator ho=_chg_hosts.begin(); ho!=_chg_hosts.end(); ho++){ XMLNode parent; _add_host_chg(root, parent, ho->second); if(ho->first.addrtype()=="ipv4"){ if(ho->first.ipv6_addr()!=""){ _add_addr(parent,ho->first.ipv6_addr(),"ipv6",""); } if(ho->first.mac_addr()!=""){ _add_addr(parent,ho->first.mac_addr(),"mac",ho->first.mac_vendor()); } } set protos = ho->first.protocols(); for(set::iterator it= protos.begin(); it!=protos.end(); it++){ vector ports = ho->first.ports(*it); for(vector::iterator po = ports.begin(); po!=ports.end(); po++){ //print any port state changes if(ho->first.port_state(*it,*po)!=ho->second.port_state(*it,*po)){ _add_port(parent,*it,*po,ho->first.port_state(*it,*po),ho->second.port_state(*it,*po)); } //print any service state changes if(!(ho->first.service(*it,*po) == ho->second.service(*it,*po))){ nService *oldServ=NULL, *newServ=NULL; if(ho->first.service(*it,*po).product() !=""){ oldServ = &ho->first.service(*it,*po); } if(ho->second.service(*it,*po).product() !=""){ newServ = &ho->first.service(*it,*po); } _add_service(parent,oldServ,newServ); } } } } } void libndiff::_delhost(XMLNode &root){ for(vector::iterator ho=_down_hosts.begin(); ho!=_down_hosts.end(); ho++){ XMLNode parent; _add_host_down(root, parent, *ho); if(ho->addrtype()=="ipv4"){ if(ho->ipv6_addr()!=""){ _add_addr(parent,ho->ipv6_addr(),"ipv6",""); } if(ho->mac_addr()!=""){ _add_addr(parent,ho->mac_addr(),"mac",ho->mac_vendor()); } } set protos = ho->protocols(); for(set::iterator it=protos.begin(); it!=protos.end(); it++){ vector ports = ho->ports(*it); for(vector::iterator po = ports.begin(); po!=ports.end(); po++){ _add_port(parent,*it,*po,ho->port_state(*it, *po),""); //print any service state changes if(ho->service(*it,*po).product() !=""){ _add_service(parent,&ho->service(*it,*po),NULL); } } } } } void libndiff::_findDiff(){ _down_hosts = _old_scan.all_hosts(); _up_hosts = _new_scan.all_hosts(); nHost *tmp_host; //first, we go through all the hosts //the ones that were only up in the first scan have gone down for(int i=_down_hosts.size()-1;i>=0;--i){ tmp_host =_new_scan.get_host(_down_hosts[i].addr()); if(tmp_host!=NULL){ //hosts that were up in both scans may have changed if(!(*tmp_host == _down_hosts[i])){ //the host has changed _chg_hosts.push_back(pair(_down_hosts[i],*tmp_host)); } _down_hosts.erase(_down_hosts.begin()+i); } } //go throuhg the remaining hosts, erase any that were up in the origonal scan //they have come up for(int i=_up_hosts.size()-1;i>=0;--i){ tmp_host =_old_scan.get_host(_up_hosts[i].addr()); if(tmp_host!=NULL){ _up_hosts.erase(_up_hosts.begin()+i); }else if(_up_hosts[i].status() != "up" ){ _up_hosts.erase(_up_hosts.begin()+i); } } //put the timestamp in our outputs XMLNode root; _add_scan(root, _old_scan.Session.start_str(), _new_scan.Session.start_str()); //enumerate the hosts that have come up _addhost(root); //enumerate the hosts that have changed _chghost(root); //enumerate the hosts that have gone down _delhost(root); } void libndiff::setPath(std::string pathOLD, std::string pathNEW){ purge(); _init_xml(); _old_scan.setfile(pathOLD); _new_scan.setfile(pathNEW); _findDiff(); _xml = _xml_node.createXMLString(true); } libndiff::libndiff(std::string pathOLD, std::string pathNEW){ setPath(pathOLD,pathNEW); } void libndiff::purge(){ _old_scan.purge(); _new_scan.purge(); _up_hosts.clear(); _down_hosts.clear(); _chg_hosts.clear(); _xml.clear(); _simple.clear(); } string libndiff::getSimple() { return _simple.str(); } string libndiff::getXML() { return _xml; }