From ff2b5eee626052e5e1165fa4859e97887834befb Mon Sep 17 00:00:00 2001 From: Vadim Kurland Date: Sat, 19 Mar 2011 18:23:36 -0700 Subject: [PATCH] * IPTImporter.cpp (pushPolicyRule): change in the importer behavior: configuration import is aborted with an appropriate error message in the log when program enounters protocol or service name that it does not recognize and can not convert to protocol or port number. We used to replace port number with some placeholder (usually 0) and mark rule as "bad" by coloring it red and adding comment. --- doc/ChangeLog | 10 + src/import/IOSImporter.cpp | 198 ++------ src/import/IOSImporter.h | 15 +- src/import/IPTImporter.cpp | 330 ++++++-------- src/import/IPTImporter.h | 16 +- src/import/Importer.cpp | 160 +++---- src/import/Importer.h | 8 +- src/import/PIXImporter.cpp | 98 +++- src/import/addressObjectMaker.cpp | 91 ++-- src/import/addressObjectMaker.h | 9 +- src/import/objectMaker.cpp | 426 +++++++++++++++++- src/import/objectMaker.h | 66 ++- src/import/serviceObjectMaker.cpp | 198 ++++---- src/import/serviceObjectMaker.h | 21 +- src/unit_tests/ImporterTest/test_data/ios.fwb | 10 +- src/unit_tests/ImporterTest/test_data/ipt.fwb | 15 +- .../ImporterTest/test_data/ipt.test | 10 +- 17 files changed, 923 insertions(+), 758 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 40c53eb4a..be5473428 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,13 @@ +2011-03-19 vadim + + * IPTImporter.cpp (pushPolicyRule): change in the importer + behavior: configuration import is aborted with an appropriate + error message in the log when program enounters protocol or + service name that it does not recognize and can not convert to + protocol or port number. We used to replace port number with some + placeholder (usually 0) and mark rule as "bad" by coloring it red + and adding comment. + 2011-03-17 vadim * PIXImporter.cpp (newObjectGroupNetwork): see #2234 Added support diff --git a/src/import/IOSImporter.cpp b/src/import/IOSImporter.cpp index 3fe178d62..035b4334b 100644 --- a/src/import/IOSImporter.cpp +++ b/src/import/IOSImporter.cpp @@ -62,47 +62,8 @@ IOSImporter::IOSImporter(FWObject *lib, const std::string &fwname) : Importer(lib, "iosacl", input, log, fwname) { address_maker->setInvertedNetmasks(true); - - cisco_icmp_specs["echo-reply"] = std::pair(0, 0); - cisco_icmp_specs["unreachable"] = std::pair(3, -1); // all "unreachables" - cisco_icmp_specs["net-unreachable"] = std::pair(3, 0); - cisco_icmp_specs["host-unreachable"] = std::pair(3, 1); - cisco_icmp_specs["protocol-unreachable"] = std::pair(3, 2); - cisco_icmp_specs["port-unreachable"] = std::pair(3, 3); - cisco_icmp_specs["packet-too-big"] = std::pair(3, 4); - cisco_icmp_specs["source-route-failed"] = std::pair(3, 5); - cisco_icmp_specs["network-unknown"] = std::pair(3, 6); - cisco_icmp_specs["host-unknown"] = std::pair(3, 7); - cisco_icmp_specs["host-isolated"] = std::pair(3, 8); - cisco_icmp_specs["dod-net-prohibited"] = std::pair(3, 9); - cisco_icmp_specs["dod-host-prohibited"] = std::pair(3, 10); - cisco_icmp_specs["net-tos-unreachable"] = std::pair(3, 11); - cisco_icmp_specs["host-tos-unreachable"] = std::pair(3, 12); - cisco_icmp_specs["administratively-prohibited"] = std::pair(3, 13); - cisco_icmp_specs["host-precedence-unreachable"] = std::pair(3, 14); - cisco_icmp_specs["precedence-unreachable"] = std::pair(3, 15); - cisco_icmp_specs["source-quench"] = std::pair(4, 0); - cisco_icmp_specs["net-redirect"] = std::pair(5, 0); - cisco_icmp_specs["host-redirect"] = std::pair(5, 1); - cisco_icmp_specs["net-tos-redirect"] = std::pair(5, 2); - cisco_icmp_specs["host-tos-redirect"] = std::pair(5, 3); - cisco_icmp_specs["echo"] = std::pair(8, 0); - cisco_icmp_specs["router-advertisement"] = std::pair(9, 0); - cisco_icmp_specs["router-solicitation"] = std::pair(10, 0); - cisco_icmp_specs["ttl-exceeded"] = std::pair(11, 0); - cisco_icmp_specs["reassembly-timeout"] = std::pair(11, 1); - cisco_icmp_specs["general-parameter-problem"] = std::pair(12, 0); - cisco_icmp_specs["option-missing"] = std::pair(12, 1); - cisco_icmp_specs["timestamp-request"] = std::pair(13, 0); - cisco_icmp_specs["timestamp-reply"] = std::pair(14, 0); - cisco_icmp_specs["information-request"] = std::pair(15, 0); - cisco_icmp_specs["information-reply"] = std::pair(16, 0); - cisco_icmp_specs["mask-request"] = std::pair(17, 0); - cisco_icmp_specs["mask-reply"] = std::pair(18, 0); } - - IOSImporter::~IOSImporter() { all_rulesets.clear(); @@ -119,151 +80,54 @@ void IOSImporter::setInterfaceAndDirectionForRuleSet( } -FWObject* IOSImporter::createICMPService(bool deduplicate) -{ -// TODO: convert icmp_spec to QString and cisco_icmp_specs to QMap - std::string icmpspec = QString(icmp_spec.c_str()).trimmed().toStdString(); - if (!icmpspec.empty()) - { - // Cisco is trying to be too helpful, they translate many - // icmp type/code combinations into stings - if (cisco_icmp_specs.count(icmpspec)!=0) - { - std::pair pp = cisco_icmp_specs[icmpspec]; - std::ostringstream s1, s2; - s1 << pp.first; - icmp_type = s1.str(); - s2 << pp.second; - icmp_code = s2.str(); - } else - { - reportError( - std::string("Import of icmp protocol '") + icmp_spec + "' failed"); - icmp_code = "-1"; - icmp_type = "-1"; - } - } - icmp_spec = ""; - - return Importer::createICMPService(deduplicate); -} - -FWObject* IOSImporter::createIPService(bool deduplicate) -{ - int proto = GetProtoByName::getProtocolByName(protocol.c_str()); - if (proto > -1) - { - std::ostringstream s; - s << proto; - protocol = s.str(); - } - return Importer::createIPService(deduplicate); -} - -int IOSImporter::convertPort(const std::string &port_str, - const std::string &proto) -{ - QString ps = QString(port_str.c_str()).trimmed(); - int port = GetServByName::getPortByName(ps, proto.c_str()); - if (port == -1) - { - reportError(std::string("Port spec '") + port_str + "' unknown "); - port = 0; - } - return port; -} - -std::pair IOSImporter::convertPortSpec(const std::string &port_op, - const std::string &port_spec, - const std::string &proto) -{ - int range_start; - int range_end; - std::string s1,s2; - - // TODO: convert port_op and port_spec to QString - std::string portop = QString(port_op.c_str()).trimmed().toStdString(); - std::string portspec = QString(port_spec.c_str()).trimmed().toStdString(); - - if (fwbdebug) - qDebug() << QString("Convert TCP/UDP port spec: port_op=%1 port_spec=%2"). - arg(port_op.c_str()).arg(port_spec.c_str()); - - if (portop=="" && portspec=="") return std::pair(0, 0); - - std::string::size_type n = portspec.find(' '); - if (n!=std::string::npos) - { - s1 = portspec.substr(0, n); - s2 = portspec.substr(n); - } else - { - s1 = portspec; - s2 = portspec; - } - range_start = convertPort(s1, proto); - range_end = convertPort(s2, proto); - - if (portop=="lt") range_start = 0; - if (portop=="gt") range_end = 65535; - if (portop=="eq") - { - range_start = range_end; - } - if (portop=="range") - { - // range_start and range_end have been set - ; - } - - return std::pair(range_start, range_end); -} - -FWObject* IOSImporter::createTCPService(bool deduplicate) +ObjectSignature IOSImporter::packObjectSignatureTCPService() { // use src_port_op, src_port_spec, dst_port_op, dst_port_spec // port_op can be: lt (less than), gt (greater than), eq (equal), // neq (not equal), and range (inclusive range). - // here we assume src_port_spec and dst_port_spec are - // both numeric and represent a single port. - std::string name = "tcp " + src_port_spec + " " + dst_port_spec; + ObjectSignature sig; + sig.type_name = TCPService::TYPENAME; - std::pair pr = - convertPortSpec(src_port_op, src_port_spec, "tcp"); - int srs = pr.first; - int sre = pr.second; + sig.setSrcPortRangeFromPortOp( + src_port_op.c_str(), src_port_spec.c_str(), protocol.c_str()); + sig.setDstPortRangeFromPortOp( + dst_port_op.c_str(), dst_port_spec.c_str(), protocol.c_str()); - pr = convertPortSpec(dst_port_op, dst_port_spec, "tcp"); - int drs = pr.first; - int dre = pr.second; + sig.established = established; + sig.flags_mask = tcp_flags_mask; + sig.flags_comp = tcp_flags_comp; - return service_maker->getTCPService(srs, sre, - drs, dre, - established, tcp_flags_mask, tcp_flags_comp, - deduplicate); + return sig; } -FWObject* IOSImporter::createUDPService(bool deduplicate) +ObjectSignature IOSImporter::packObjectSignatureUDPService() { // use src_port_op, src_port_spec, dst_port_op, dst_port_spec // port_op can be: lt (less than), gt (greater than), eq (equal), // neq (not equal), and range (inclusive range). - // here we assume src_port_spec and dst_port_spec are - // both numeric and represent a single port. - std::string name = "udp " + src_port_spec + " " + dst_port_spec; + ObjectSignature sig; + sig.type_name = UDPService::TYPENAME; - std::pair pr = - convertPortSpec(src_port_op, src_port_spec, "udp"); - int srs = pr.first; - int sre = pr.second; + sig.setSrcPortRangeFromPortOp( + src_port_op.c_str(), src_port_spec.c_str(), protocol.c_str()); + sig.setDstPortRangeFromPortOp( + dst_port_op.c_str(), dst_port_spec.c_str(), protocol.c_str()); - pr = convertPortSpec(dst_port_op, dst_port_spec, "udp"); - int drs = pr.first; - int dre = pr.second; + return sig; +} - return service_maker->getUDPService(srs, sre, drs, dre, deduplicate); +FWObject* IOSImporter::createTCPService() +{ + ObjectSignature sig = packObjectSignatureTCPService(); + return service_maker->createObject(sig); +} + +FWObject* IOSImporter::createUDPService() +{ + ObjectSignature sig = packObjectSignatureUDPService(); + return service_maker->createObject(sig); } void IOSImporter::ignoreCurrentInterface() @@ -446,7 +310,7 @@ Firewall* IOSImporter::finalize() } } } - qDebug("ruleset done"); + // qDebug("ruleset done"); // call clearChidren() not recursive because children objects // of all rules should not be deleted diff --git a/src/import/IOSImporter.h b/src/import/IOSImporter.h index 77615b635..43f110890 100644 --- a/src/import/IOSImporter.h +++ b/src/import/IOSImporter.h @@ -43,20 +43,13 @@ class IOSImporter : public Importer { - std::map > cisco_icmp_specs; - protected: - virtual libfwbuilder::FWObject* createIPService(bool deduplicate=true); - virtual libfwbuilder::FWObject* createICMPService(bool deduplicate=true); - virtual libfwbuilder::FWObject* createTCPService(bool deduplicate=true); - virtual libfwbuilder::FWObject* createUDPService(bool deduplicate=true); + virtual libfwbuilder::FWObject* createTCPService(); + virtual libfwbuilder::FWObject* createUDPService(); - int convertPort(const std::string &port, const std::string &proto); - - std::pair convertPortSpec(const std::string &port_op, - const std::string &port_spec, - const std::string &proto); + virtual ObjectSignature packObjectSignatureTCPService(); + virtual ObjectSignature packObjectSignatureUDPService(); public: diff --git a/src/import/IPTImporter.cpp b/src/import/IPTImporter.cpp index 5a70111ab..9e9cdc16b 100644 --- a/src/import/IPTImporter.cpp +++ b/src/import/IPTImporter.cpp @@ -75,49 +75,6 @@ IPTImporter::IPTImporter(FWObject *lib, clear(); - icmp_specs["any"] << "-1" << "-1"; - icmp_specs["echo-reply"] << "0" << "0"; - // all "unreachables" - icmp_specs["destination-unreachable"] << "3" << "-1"; - icmp_specs["network-unreachable"] << "3" << "0"; - icmp_specs["host-unreachable"] << "3" << "1"; - icmp_specs["protocol-unreachable"] << "3" << "2"; - icmp_specs["port-unreachable"] << "3" << "3"; - icmp_specs["fragmentation-needed"] << "3" << "4"; - icmp_specs["source-route-failed"] << "3" << "5"; - icmp_specs["network-unknown"] << "3" << "6"; - icmp_specs["host-unknown"] << "3" << "7"; - icmp_specs["host-isolated"] << "3" << "8"; - icmp_specs["network-prohibited"] << "3" << "9"; - icmp_specs["host-prohibited"] << "3" << "10"; - icmp_specs["TOS-network-unreachable"] << "3" << "11"; - icmp_specs["TOS-host-unreachable"] << "3" << "12"; - icmp_specs["communication-prohibited"] << "3" << "13"; - icmp_specs["host-precedence-violation"] << "3" << "14"; - icmp_specs["precedence-cutoff"] << "3" << "15"; - icmp_specs["source-quench"] << "4" << "0"; - icmp_specs["redirect"] << "5" << "-1"; - icmp_specs["network-redirect"] << "5" << "0"; - icmp_specs["host-redirect"] << "5" << "1"; - icmp_specs["TOS-network-redirect"] << "5" << "2"; - icmp_specs["TOS-host-redirect"] << "5" << "3"; - icmp_specs["echo-request"] << "8" << "0"; - icmp_specs["router-advertisement"] << "9" << "0"; - icmp_specs["router-solicitation"] << "10" << "0"; - icmp_specs["ttl-exceeded"] << "11" << "0"; - icmp_specs["time-exceeded"] << "11" << "0"; - icmp_specs["ttl-zero-during-transit"] << "11" << "0"; - icmp_specs["ttl-zero-during-reassembly"] << "11" << "1"; - icmp_specs["parameter-problem"] << "12" << "0"; - icmp_specs["ip-header-bad"] << "12" << "0"; - icmp_specs["required-option-missing"] << "12" << "1"; - icmp_specs["timestamp-request"] << "13" << "0"; - icmp_specs["timestamp-reply"] << "14" << "0"; - icmp_specs["information-request"] << "15" << "0"; - icmp_specs["information-reply"] << "16" << "0"; - icmp_specs["address-mask-request"] << "17" << "0"; - icmp_specs["address-mask-reply"] << "18" << "0"; - // mapping between REJECT target argument and our internal name for it. // See also comment in IPTImporter::pushPolicyRule() reject_action_arg_mapping["icmp-net-unreachable"] = "ICMP net unreachable"; @@ -222,84 +179,9 @@ void IPTImporter::pushTmpPortSpecToBothPortList() str_tuple( tmp_port_range_start, tmp_port_range_end ) ); } - -FWObject* IPTImporter::createICMPService(bool deduplicate) -{ - // TODO: convert icmp_spec to QString - QString icmpspec = QString(icmp_spec.c_str()).trimmed(); - if ( ! icmpspec.isEmpty()) - { - // Cisco is trying to be too helpful, they translate many - // icmp type/code combinations into stings - if (icmp_specs.count(icmpspec) > 0) - { - QStringList pp = icmp_specs[icmpspec]; - icmp_type = pp[0].toStdString(); - icmp_code = pp[1].toStdString(); - } else - { - QString err("Import of icmp protocol %1 failed"); - reportError(err.arg(icmpspec)); - icmp_code = "-1"; - icmp_type = "-1"; - } - } - icmp_spec = ""; - - return Importer::createICMPService(deduplicate); -} - -FWObject* IPTImporter::createIPService(bool deduplicate) -{ - int proto = GetProtoByName::getProtocolByName(protocol.c_str()); - if (proto > -1) - { - std::ostringstream s; - s << proto; - protocol = s.str(); - //free(pe); - } - return Importer::createIPService(deduplicate); - - // struct protoent *pe = getprotobyname(protocol.c_str()); - // if (pe!=NULL) - // { - // std::ostringstream s; - // s << pe->p_proto; - // protocol = s.str(); - // //free(pe); - // } - // return Importer::createIPService(); -} - -std::pair IPTImporter::convertPortRange(str_tuple &range, - const char *proto) -{ - return std::pair(convertPort(range.first, proto, 0), - convertPort(range.second, proto, 65535)); -} - -int IPTImporter::convertPort(const std::string &port_spec, - const char *proto, - int default_port) -{ - QString ps = QString(port_spec.c_str()).trimmed(); - if (ps == "") return 0; - if (ps == ":") return default_port; - - int port = GetServByName::getPortByName(ps, proto); - if (port == -1) - { - reportError(QString("Port spec %1 is unknown").arg(ps)); - port = 0; - } - return port; -} - FWObject* IPTImporter::createTCPUDPService(str_tuple &src_range, str_tuple &dst_range, - const std::string &proto, - bool deduplicate) + const std::string &proto) { if (fwbdebug) { @@ -314,32 +196,30 @@ FWObject* IPTImporter::createTCPUDPService(str_tuple &src_range, << dst_range.second.c_str(); } -// std::string name = proto + " " -// + src_range.first + "-" + src_range.second + -// + ":" -// + dst_range.first + "-" + dst_range.second; + ObjectSignature sig; + sig.setSrcPortRange(src_range.first.c_str(), src_range.second.c_str(), + proto.c_str()); + sig.setDstPortRange(dst_range.first.c_str(), dst_range.second.c_str(), + proto.c_str()); - std::pair pr = convertPortRange(src_range, proto.c_str()); - int srs = pr.first; - int sre = pr.second; - - pr = convertPortRange(dst_range, proto.c_str()); - int drs = pr.first; - int dre = pr.second; - - FWObject *o; if (proto=="tcp") { - o = service_maker->getTCPService(srs, sre, - drs, dre, - established, - tcp_flags_mask, tcp_flags_comp, deduplicate); + sig.type_name = TCPService::TYPENAME; + sig.established = established; + sig.flags_mask = tcp_flags_mask; + sig.flags_comp = tcp_flags_comp; } else - o = service_maker->getUDPService(srs, sre, drs, dre, deduplicate); - return commitObject(o); + { + sig.type_name = UDPService::TYPENAME; + } + + return commitObject( service_maker->createObject(sig)); } -FWObject* IPTImporter::createTCPUDPService(const std::string &proto, bool deduplicate) +/* + * TODO: fix this + */ +FWObject* IPTImporter::createTCPUDPService(const std::string &proto) { str_tuple empty_range("0","0"); @@ -372,7 +252,7 @@ FWObject* IPTImporter::createTCPUDPService(const std::string &proto, bool dedupl o = createTCPUDPService( (list_ptr == &src_port_list) ? *i : empty_range, (list_ptr == &dst_port_list) ? *i : empty_range, - proto, deduplicate); + proto); olist.push_back(o); list_names.push_back(o->getName()); @@ -404,18 +284,18 @@ FWObject* IPTImporter::createTCPUDPService(const std::string &proto, bool dedupl return createTCPUDPService( (src_port_list.size()>0) ? src_port_list.front() : empty_range, (dst_port_list.size()>0) ? dst_port_list.front() : empty_range, - proto, deduplicate); + proto); } } -FWObject* IPTImporter::createTCPService(bool deduplicate) +FWObject* IPTImporter::createTCPService() { - return createTCPUDPService("tcp", deduplicate); + return createTCPUDPService("tcp"); } -FWObject* IPTImporter::createUDPService(bool deduplicate) +FWObject* IPTImporter::createUDPService() { - return createTCPUDPService("udp", deduplicate); + return createTCPUDPService("udp"); } @@ -423,9 +303,12 @@ FWObject* IPTImporter::makeSrcObj() { if (using_iprange_src) { - return commitObject( - address_maker->createAddressRange(iprange_src_from.c_str(), - iprange_src_to.c_str())); + ObjectSignature sig; + sig.type_name = AddressRange::TYPENAME; + sig.address_range_start = iprange_src_from.c_str(); + sig.address_range_end = iprange_src_to.c_str(); + + return commitObject(address_maker->createObject(sig)); } else return Importer::makeSrcObj(); } @@ -434,9 +317,12 @@ FWObject* IPTImporter::makeDstObj() { if (using_iprange_dst) { - return commitObject( - address_maker->createAddressRange(iprange_dst_from.c_str(), - iprange_dst_to.c_str())); + ObjectSignature sig; + sig.type_name = AddressRange::TYPENAME; + sig.address_range_start = iprange_dst_from.c_str(); + sig.address_range_end = iprange_dst_to.c_str(); + + return commitObject(address_maker->createObject(sig)); } else return Importer::makeDstObj(); } @@ -551,7 +437,10 @@ void IPTImporter::addMarkMatch(PolicyRule *rule) assert(srv!=NULL); if (rule->getSrv()->isAny() && !match_mark.empty()) { - srv->addRef( commitObject(service_maker->getTagService(match_mark.c_str())) ); + ObjectSignature sig; + sig.type_name = TagService::TYPENAME; + sig.tag = match_mark.c_str(); + srv->addRef( commitObject(service_maker->createObject(sig)) ); if (neg_match_mark) srv->setNeg(true); match_mark = ""; } @@ -564,11 +453,12 @@ void IPTImporter::addLengthMatch(PolicyRule *rule) if (rule->getSrv()->isAny() && !length_spec.empty()) { // create custom service with module "length" - srv->addRef(commitObject( - service_maker->getCustomService( - "iptables", - QString("-m length --length %1").arg(length_spec.c_str()), - ""))); + ObjectSignature sig; + sig.type_name = CustomService::TYPENAME; + sig.platform = "iptables"; + sig.code = QString("-m length --length %1").arg(length_spec.c_str()); + sig.protocol_name = ""; + srv->addRef(commitObject(service_maker->createObject(sig))); length_spec = ""; } } @@ -580,11 +470,12 @@ void IPTImporter::addPktTypeMatch(PolicyRule *rule) if (rule->getSrv()->isAny() && !pkt_type_spec.empty()) { // create custom service with module "pkttype" - srv->addRef(commitObject( - service_maker->getCustomService( - "iptables", - QString("-m pkttype --pkt-type %1").arg(pkt_type_spec.c_str()), - ""))); + ObjectSignature sig; + sig.type_name = CustomService::TYPENAME; + sig.platform = "iptables"; + sig.code = QString("-m pkttype --pkt-type %1").arg(pkt_type_spec.c_str()); + sig.protocol_name = ""; + srv->addRef(commitObject(service_maker->createObject(sig))); pkt_type_spec = ""; } } @@ -611,11 +502,13 @@ void IPTImporter::addRecentMatch(PolicyRule *rule) if (rule->getSrv()->isAny() && !recent_match.empty()) { // create custom service with module "recent" - srv->addRef(commitObject( - service_maker->getCustomService( - "iptables", - QString("-m recent %1").arg(recent_match.c_str()), - ""))); + ObjectSignature sig; + sig.type_name = CustomService::TYPENAME; + sig.platform = "iptables"; + sig.code = QString("-m recent %1").arg(recent_match.c_str()); + sig.protocol_name = ""; + srv->addRef(commitObject(service_maker->createObject(sig))); + recent_match = ""; } } @@ -627,11 +520,12 @@ void IPTImporter::addStateMatch(libfwbuilder::PolicyRule *rule, const string &st if (rule->getSrv()->isAny() && !state.empty()) { // create custom service with module "state" - srv->addRef(commitObject( - service_maker->getCustomService( - "iptables", - QString("-m state --state %1").arg(state.c_str()), - ""))); + ObjectSignature sig; + sig.type_name = CustomService::TYPENAME; + sig.platform = "iptables"; + sig.code = QString("-m state --state %1").arg(state.c_str()); + sig.protocol_name = ""; + srv->addRef(commitObject(service_maker->createObject(sig))); recent_match = ""; } } @@ -807,12 +701,14 @@ void IPTImporter::pushPolicyRule() action_on_reject_code = "ICMP admin prohibited"; QString err = QObject::tr( - "Warning: Line %1: Unknown parameter of target REJECT: %2.\n") + "Error: Line %1: Unknown parameter of target REJECT: %2.\n") .arg(getCurrentLineNumber()) .arg(iptables_reject_arg); - ropt->setStr("color", getBadRuleColor()); - rule_comment += string(err.toUtf8().constData()); - *Importer::logger << err.toUtf8().constData(); + throw ImporterException(err); + + // ropt->setStr("color", getBadRuleColor()); + // rule_comment += string(err.toUtf8().constData()); + // *Importer::logger << err.toUtf8().constData(); } ropt->setStr("action_on_reject", action_on_reject_code.toStdString()); @@ -887,9 +783,11 @@ void IPTImporter::pushPolicyRule() { action = PolicyRule::Tag; last_mark_rule = rule; - std::string mark_code = action_params["set_mark"]; - FWObject *tag_service = commitObject( - service_maker->getTagService(mark_code.c_str())); + + ObjectSignature sig; + sig.type_name = TagService::TYPENAME; + sig.tag = action_params["set_mark"].c_str(); + FWObject *tag_service = commitObject(service_maker->createObject(sig)); rule->setTagObject(tag_service); } if (target=="CONNMARK") action = PolicyRule::Continue; @@ -989,9 +887,12 @@ void IPTImporter::pushPolicyRule() estab = std_obj->findObjectByName(CustomService::TYPENAME, "ESTABLISHED"); if (estab == NULL) { - estab = commitObject( - service_maker->getCustomService( - "iptables", "-m state --state RELATED,ESTABLISHED", "")); + ObjectSignature sig; + sig.type_name = CustomService::TYPENAME; + sig.platform = "iptables"; + sig.code = QString("-m state --state RELATED,ESTABLISHED"); + sig.protocol_name = ""; + estab = service_maker->createObject(sig); } if (!rule->getSrv()->isAny()) @@ -1048,11 +949,12 @@ void IPTImporter::pushPolicyRule() { RuleElementSrv *srv = rule->getSrv(); - FWObject *state_match_srv = commitObject( - service_maker->getCustomService( - "iptables", - QString("-m state --state %1").arg(current_state.c_str()), - "")); + ObjectSignature sig; + sig.type_name = CustomService::TYPENAME; + sig.platform = "iptables"; + sig.code = QString("-m state --state %1").arg(current_state.c_str()); + sig.protocol_name = ""; + FWObject *state_match_srv = commitObject(service_maker->createObject(sig)); if ( ! rule->getSrv()->isAny()) { @@ -1302,11 +1204,20 @@ void IPTImporter::pushNATRule() FWObject *tsrc = NULL; if (nat_addr1!=nat_addr2) - tsrc = commitObject( - address_maker->createAddressRange(nat_addr1.c_str(), nat_addr2.c_str())); - else - tsrc = commitObject( - address_maker->createAddress(nat_addr1.c_str(), nat_nm.c_str())); + { + ObjectSignature sig; + sig.type_name = AddressRange::TYPENAME; + sig.address_range_start = nat_addr1.c_str(); + sig.address_range_end = nat_addr2.c_str(); + tsrc = commitObject(address_maker->createObject(sig)); + } else + { + ObjectSignature sig; + sig.type_name = Address::TYPENAME; + sig.address = nat_addr1.c_str(); + sig.netmask = nat_nm.c_str(); + tsrc = commitObject(address_maker->createObject(sig)); + } RuleElementTSrc *re = rule->getTSrc(); assert(re!=NULL); @@ -1347,11 +1258,20 @@ void IPTImporter::pushNATRule() FWObject *tdst = NULL; if (nat_addr1!=nat_addr2) - tdst = commitObject( - address_maker->createAddressRange(nat_addr1.c_str(), nat_addr2.c_str())); - else - tdst = commitObject( - address_maker->createAddress(nat_addr1.c_str(), nat_nm.c_str())); + { + ObjectSignature sig; + sig.type_name = AddressRange::TYPENAME; + sig.address_range_start = nat_addr1.c_str(); + sig.address_range_end = nat_addr2.c_str(); + tdst = commitObject(address_maker->createObject(sig)); + } else + { + ObjectSignature sig; + sig.type_name = Address::TYPENAME; + sig.address = nat_addr1.c_str(); + sig.netmask = nat_nm.c_str(); + tdst = commitObject(address_maker->createObject(sig)); + } RuleElementTDst *re = rule->getTDst(); assert(re!=NULL); @@ -1415,8 +1335,12 @@ void IPTImporter::pushNATRule() RuleElementTSrc *tsrc = rule->getTSrc(); assert(tsrc!=NULL); - o = commitObject( - address_maker->createAddress(nat_addr1.c_str(), nat_nm.c_str())); + + ObjectSignature sig; + sig.type_name = Address::TYPENAME; + sig.address = nat_addr1.c_str(); + sig.netmask = nat_nm.c_str(); + o = commitObject(address_maker->createObject(sig)); tsrc->addRef(o); } @@ -1426,8 +1350,12 @@ void IPTImporter::pushNATRule() RuleElementTDst *tdst = rule->getTDst(); assert(tdst!=NULL); - o = commitObject( - address_maker->createAddress(nat_addr1.c_str(), nat_nm.c_str())); + + ObjectSignature sig; + sig.type_name = Address::TYPENAME; + sig.address = nat_addr1.c_str(); + sig.netmask = nat_nm.c_str(); + o = commitObject(address_maker->createObject(sig)); tdst->addRef(o); } } diff --git a/src/import/IPTImporter.h b/src/import/IPTImporter.h index 2fff48ae7..425b029c6 100644 --- a/src/import/IPTImporter.h +++ b/src/import/IPTImporter.h @@ -48,29 +48,21 @@ typedef std::pair str_tuple; class IPTImporter : public Importer { - QMap icmp_specs; QMap reject_action_arg_mapping; int aux_branch_number; libfwbuilder::FWObject* createTCPUDPService(str_tuple &src_range, str_tuple &dst_range, - const std::string &proto, - bool deduplicate=true); + const std::string &proto); - libfwbuilder::FWObject* createTCPUDPService(const std::string &proto, - bool deduplicate=true); + libfwbuilder::FWObject* createTCPUDPService(const std::string &proto); - virtual libfwbuilder::FWObject* createIPService(bool deduplicate=true); - virtual libfwbuilder::FWObject* createICMPService(bool deduplicate=true); - virtual libfwbuilder::FWObject* createTCPService(bool deduplicate=true); - virtual libfwbuilder::FWObject* createUDPService(bool deduplicate=true); + virtual libfwbuilder::FWObject* createTCPService(); + virtual libfwbuilder::FWObject* createUDPService(); virtual libfwbuilder::FWObject* makeSrcObj(); virtual libfwbuilder::FWObject* makeDstObj(); - std::pair convertPortRange(str_tuple &range, const char *proto); - int convertPort(const std::string &port_spec, const char *proto, int default_port); - void processModuleMatches(); void addAllModuleMatches(libfwbuilder::PolicyRule *rule); void addMarkMatch(libfwbuilder::PolicyRule *rule); diff --git a/src/import/Importer.cpp b/src/import/Importer.cpp index 56f31c5b3..921a6f83d 100644 --- a/src/import/Importer.cpp +++ b/src/import/Importer.cpp @@ -503,6 +503,8 @@ void Importer::pushRule() assert(current_rule!=NULL); // populate all elements of the rule + //qDebug() << QString("Adding rule from line %1") .arg(getCurrentLineNumber()); + PolicyRule *rule = PolicyRule::cast(current_rule); if (action=="permit") rule->setAction(PolicyRule::Accept); @@ -517,8 +519,7 @@ void Importer::pushRule() // then add it to the current ruleset current_ruleset->ruleset->add(current_rule); - addStandardImportComment( - current_rule, QString::fromUtf8(rule_comment.c_str())); + addStandardImportComment(current_rule, QString::fromUtf8(rule_comment.c_str())); current_rule = NULL; rule_comment = ""; @@ -532,9 +533,14 @@ FWObject* Importer::makeSrcObj() (src_a==InetAddr::getAny().toString() && src_nm==InetAddr::getAny().toString())) return NULL; // this is 'any' - if (src_nm=="") src_nm=InetAddr::getAllOnes().toString(); - return commitObject( - address_maker->createAddress(src_a.c_str(), src_nm.c_str())); + if (src_nm=="") src_nm = InetAddr::getAllOnes().toString(); + + ObjectSignature sig; + sig.type_name = Address::TYPENAME; + sig.address = src_a.c_str(); + sig.netmask = src_nm.c_str(); + + return commitObject(address_maker->createObject(sig)); } FWObject* Importer::makeDstObj() @@ -544,21 +550,52 @@ FWObject* Importer::makeDstObj() dst_nm==InetAddr::getAny().toString())) return NULL; // this is 'any' if (dst_nm=="") dst_nm=InetAddr::getAllOnes().toString(); - return commitObject( - address_maker->createAddress(dst_a.c_str(), dst_nm.c_str())); + + ObjectSignature sig; + sig.type_name = Address::TYPENAME; + sig.address = dst_a.c_str(); + sig.netmask = dst_nm.c_str(); + + return commitObject(address_maker->createObject(sig)); } FWObject* Importer::makeSrvObj() { if (protocol=="") return NULL; // this is 'any' FWObject *s; - if (protocol=="icmp") s = createICMPService(); - else - if (protocol=="tcp") s = createTCPService(); - else - if (protocol=="udp") s = createUDPService(); - else - s = createIPService(); + if (protocol=="icmp") + { + ObjectSignature sig; + sig.type_name = ICMPService::TYPENAME; + if ( ! icmp_spec.empty()) + { + sig.setIcmpFromName(icmp_spec.c_str()); + } else + { + sig.setIcmpType(icmp_type.c_str()); + sig.setIcmpCode(icmp_code.c_str()); + } + s = service_maker->createObject(sig); + } else + { + if (protocol=="tcp") + { + s = createTCPService(); + } else + { + if (protocol=="udp") + { + s = createUDPService(); + } else + { + ObjectSignature sig; + sig.type_name = IPService::TYPENAME; + sig.setProtocol(protocol.c_str()); + sig.fragments = fragments; + s = service_maker->createObject(sig); + } + } + } // if create*Service returns NULL, this is 'any' return commitObject(s); } @@ -622,103 +659,16 @@ Firewall* Importer::finalize() return fw; } -FWObject* Importer::createICMPService(bool deduplicate) -{ - int type, code; - - // TODO: convert icmp_type and icmp_code to QString - QString icmp_type_qs = QString(icmp_type.c_str()).trimmed(); - QString icmp_code_qs = QString(icmp_code.c_str()).trimmed(); - - if (icmp_type_qs.isEmpty()) type = -1; - else - { - bool ok = false; - type = icmp_type_qs.toInt(&ok); - if (!ok) - { - // could not convert - type = -1; - QString err("ICMP type %1 is unknown"); - reportError(err.arg(icmp_type_qs)); - } - } - - if (icmp_code_qs.isEmpty()) code = -1; - else - { - bool ok = false; - code = icmp_code_qs.toInt(&ok); - if (!ok) - { - // could not convert - type = -1; - QString err("ICMP code %1 is unknown"); - reportError(err.arg(icmp_code_qs)); - } - } - - return service_maker->getICMPService(type, code, deduplicate); -} - -FWObject* Importer::createIPService(bool deduplicate) -{ - // this assumes protocol is represented by a number - bool ok = false; - int proto_num = QString(protocol.c_str()).toInt(&ok); - if ( ! ok) - { - // could not convert protocol number - proto_num = 0; - reportError(QString("Protocol '%1' is unknown").arg(protocol.c_str())); - } - return service_maker->getIPService(proto_num, fragments, deduplicate); -} - -FWObject* Importer::createTCPService(bool deduplicate) +FWObject* Importer::createTCPService() { // Default implementation - // - // use src_port_spec, dst_port_spec - // - // here we assume src_port_spec and dst_port_spec are - // both numeric and represent a single port. - - std::string name = "tcp " + src_port_spec + " " + dst_port_spec; - - std::istringstream src_str(src_port_spec); - std::istringstream dst_str(dst_port_spec); - int sport, dport; - - src_str >> sport; - dst_str >> dport; - - return service_maker->getTCPService(sport, sport, - dport, dport, - established, - tcp_flags_mask, tcp_flags_comp, - deduplicate); + return NULL; } -FWObject* Importer::createUDPService(bool deduplicate) +FWObject* Importer::createUDPService() { // Default implementation - // - // use src_port_spec, dst_port_spec - // - // here we assume src_port_spec and dst_port_spec are - // both numeric and represent a single port. - - std::string name = "udp " + src_port_spec + " " + dst_port_spec; - - std::istringstream src_str(src_port_spec); - std::istringstream dst_str(dst_port_spec); - int sport, dport; - - src_str >> sport; - dst_str >> dport; - - return service_maker->getUDPService(sport, sport, dport, dport, deduplicate); + return NULL; } FWObject* Importer::createGroupOfInterfaces( diff --git a/src/import/Importer.h b/src/import/Importer.h index d7633e8cd..0a347482f 100644 --- a/src/import/Importer.h +++ b/src/import/Importer.h @@ -164,11 +164,9 @@ protected: // exists, it is created virtual UnidirectionalRuleSet* getUnidirRuleSet( const std::string &ruleset_name, const std::string &ruleset_type_name); - - virtual libfwbuilder::FWObject* createIPService(bool deduplicate=true); - virtual libfwbuilder::FWObject* createICMPService(bool deduplicate=true); - virtual libfwbuilder::FWObject* createTCPService(bool deduplicate=true); - virtual libfwbuilder::FWObject* createUDPService(bool deduplicate=true); + + virtual libfwbuilder::FWObject* createTCPService(); + virtual libfwbuilder::FWObject* createUDPService(); // create libfwbuilder::ObjectGroup and place all interfaces in it // argument represents a list of interface names diff --git a/src/import/PIXImporter.cpp b/src/import/PIXImporter.cpp index 4332f6e6e..77e9253f2 100644 --- a/src/import/PIXImporter.cpp +++ b/src/import/PIXImporter.cpp @@ -35,6 +35,7 @@ #include "interfaceProperties.h" #include "interfacePropertiesObjectFactory.h" +#include "fwbuilder/AddressRange.h" #include "fwbuilder/Resources.h" #include "fwbuilder/Network.h" #include "fwbuilder/Address.h" @@ -45,6 +46,7 @@ #include "fwbuilder/UDPService.h" #include "fwbuilder/Policy.h" #include "fwbuilder/RuleElement.h" +#include "fwbuilder/Library.h" #include #include @@ -364,42 +366,65 @@ void PIXImporter::newNamedObjectService(const string &name) void PIXImporter::commitNamedAddressObject() { - current_named_object = commitObject( - address_maker->createAddress(tmp_a.c_str(), tmp_nm.c_str(), false)); - setNameOfNamedObject(current_named_object); + ObjectSignature sig; + sig.object_name = named_object_name; + sig.type_name = Address::TYPENAME; + sig.address = tmp_a.c_str(); + sig.netmask = tmp_nm.c_str(); + current_named_object = commitObject(address_maker->createObject(sig)); named_objects_registry[named_object_name] = current_named_object; } void PIXImporter::commitNamedAddressRangeObject() { - current_named_object = commitObject( - address_maker->createAddressRange( - tmp_range_1.c_str(), tmp_range_2.c_str(), false)); - setNameOfNamedObject(current_named_object); + ObjectSignature sig; + sig.object_name = named_object_name; + sig.type_name = AddressRange::TYPENAME; + sig.address_range_start = tmp_range_1.c_str(); + sig.address_range_end = tmp_range_2.c_str(); + current_named_object = commitObject(address_maker->createObject(sig)); named_objects_registry[named_object_name] = current_named_object; } void PIXImporter::commitNamedIPServiceObject() { - current_named_object = commitObject(createIPService(false)); - setNameOfNamedObject(current_named_object); + ObjectSignature sig; + sig.object_name = named_object_name; + sig.type_name = IPService::TYPENAME; + sig.setProtocol(protocol.c_str()); + sig.fragments = fragments; + current_named_object = commitObject(service_maker->createObject(sig)); named_objects_registry[named_object_name] = current_named_object; } void PIXImporter::commitNamedICMPServiceObject() { - current_named_object = commitObject(createICMPService(false)); - setNameOfNamedObject(current_named_object); + ObjectSignature sig; + sig.object_name = named_object_name; + sig.type_name = ICMPService::TYPENAME; + + if ( ! icmp_spec.empty()) + { + sig.setIcmpFromName(icmp_spec.c_str()); + } else + { + sig.setIcmpType(icmp_type.c_str()); + sig.setIcmpCode(icmp_code.c_str()); + } + + current_named_object = commitObject(service_maker->createObject(sig)); named_objects_registry[named_object_name] = current_named_object; } void PIXImporter::commitNamedTCPUDPServiceObject() { - FWObject *new_obj = NULL; - if (protocol == "tcp") new_obj = createTCPService(false); - if (protocol == "udp") new_obj = createUDPService(false); - current_named_object = commitObject(new_obj); - setNameOfNamedObject(current_named_object); + ObjectSignature sig; + if (protocol == "tcp") sig = packObjectSignatureTCPService(); + if (protocol == "udp") sig = packObjectSignatureUDPService(); + + sig.object_name = named_object_name; + + current_named_object = commitObject(service_maker->createObject(sig)); named_objects_registry[named_object_name] = current_named_object; } @@ -450,10 +475,11 @@ void PIXImporter::newObjectGroupNetwork(const string &name) object_group_name = QString::fromUtf8(name.c_str()); object_group_comment = ""; + ObjectMaker maker(Library::cast(library)); current_object_group = setNameOfNamedObject( commitObject( - address_maker->createObject(ObjectGroup::TYPENAME, name))); + maker.createObject(ObjectGroup::TYPENAME, name))); named_objects_registry[object_group_name] = current_object_group; *logger << "Object Group (network) " + name; @@ -464,10 +490,11 @@ void PIXImporter::newObjectGroupService(const string &name) object_group_name = QString::fromUtf8(name.c_str()); object_group_comment = ""; + ObjectMaker maker(Library::cast(library)); current_object_group = setNameOfNamedObject( commitObject( - address_maker->createObject(ServiceGroup::TYPENAME, name))); + maker.createObject(ServiceGroup::TYPENAME, name))); named_objects_registry[object_group_name] = current_object_group; *logger << "Object Group (service) " + name; @@ -478,10 +505,11 @@ void PIXImporter::newObjectGroupProtocol(const string &name) object_group_name = QString::fromUtf8(name.c_str()); object_group_comment = ""; + ObjectMaker maker(Library::cast(library)); current_object_group = setNameOfNamedObject( commitObject( - address_maker->createObject(ServiceGroup::TYPENAME, name))); + maker.createObject(ServiceGroup::TYPENAME, name))); named_objects_registry[object_group_name] = current_object_group; *logger << "Object Group (protocol) " + name; @@ -492,10 +520,11 @@ void PIXImporter::newObjectGroupICMP(const string &name) object_group_name = QString::fromUtf8(name.c_str()); object_group_comment = ""; + ObjectMaker maker(Library::cast(library)); current_object_group = setNameOfNamedObject( commitObject( - address_maker->createObject(ServiceGroup::TYPENAME, name))); + maker.createObject(ServiceGroup::TYPENAME, name))); named_objects_registry[object_group_name] = current_object_group; *logger << "Object Group (icmp) " + name; @@ -514,9 +543,12 @@ void PIXImporter::setObjectGroupDescription(const std::string &descr) void PIXImporter::addNetworkToObjectGroup() { - FWObject *obj = commitObject( - address_maker->createAddress(tmp_a.c_str(), tmp_nm.c_str())); - current_object_group->addRef(obj); + ObjectSignature sig; + sig.type_name = Address::TYPENAME; + sig.address = tmp_a.c_str(); + sig.netmask = tmp_nm.c_str(); + current_object_group->addRef( + commitObject(address_maker->createObject(sig))); } void PIXImporter::addNamedObjectToObjectGroup(const std::string &object_name) @@ -533,7 +565,11 @@ void PIXImporter::addNamedObjectToObjectGroup(const std::string &object_name) void PIXImporter::addIPServiceToObjectGroup() { - FWObject *s = createIPService(); + ObjectSignature sig; + sig.type_name = IPService::TYPENAME; + sig.setProtocol(protocol.c_str()); + sig.fragments = fragments; + FWObject *s = service_maker->createObject(sig); current_object_group->addRef(s); } @@ -548,7 +584,19 @@ void PIXImporter::addTCPUDPServiceToObjectGroup() void PIXImporter::addICMPServiceToObjectGroup() { - FWObject *s = commitObject(createICMPService()); + ObjectSignature sig; + sig.type_name = ICMPService::TYPENAME; + + if ( ! icmp_spec.empty()) + { + sig.setIcmpFromName(icmp_spec.c_str()); + } else + { + sig.setIcmpType(icmp_type.c_str()); + sig.setIcmpCode(icmp_code.c_str()); + } + + FWObject *s = service_maker->createObject(sig); current_object_group->addRef(s); } diff --git a/src/import/addressObjectMaker.cpp b/src/import/addressObjectMaker.cpp index 523dcfe23..8392c7bfa 100644 --- a/src/import/addressObjectMaker.cpp +++ b/src/import/addressObjectMaker.cpp @@ -34,16 +34,41 @@ #include "QStringListOperators.h" +#include + extern int fwbdebug; using namespace libfwbuilder; using namespace std; + AddressObjectMaker::~AddressObjectMaker() {} +FWObject* AddressObjectMaker::createObject(ObjectSignature &sig) +{ + assert( ! sig.type_name.isEmpty()); + + FWObject *obj = findMatchingObject(sig); + if (obj) return obj; + + if (sig.type_name == AddressRange::TYPENAME) + obj = createAddressRange(sig.address_range_start, sig.address_range_end); + else + obj = createAddress(sig.address, sig.netmask); + + if ( ! sig.object_name.isEmpty()) + { + obj->setName(sig.object_name.toUtf8().constData()); + registerNamedObject(sig, obj); + } else + registerAnonymousObject(sig, obj); + + return obj; +} + + FWObject* AddressObjectMaker::createAddress(const QString &addr, - const QString &netmask, - bool deduplicate) + const QString &netmask) { QString correct_nm = netmask; if (inverted_netmasks) @@ -57,65 +82,33 @@ FWObject* AddressObjectMaker::createAddress(const QString &addr, QString name; try { - ObjectSignature sig; - sig.type_name = IPv4::TYPENAME; - sig.address = addr; - sig.netmask = correct_nm; - - if (deduplicate) - { - FWObject *obj = findMatchingObject(sig); - if (obj) return obj; - } - InetAddr obj_addr(addr.toStdString()); // testing if string converts to an address name = QString("h-") + addr; Address *a = Address::cast( - createObject(IPv4::TYPENAME, name.toStdString())); + ObjectMaker::createObject(IPv4::TYPENAME, name.toStdString())); a->setAddress(obj_addr); a->setNetmask(InetAddr(InetAddr::getAllOnes())); - registerObject(sig, a); return a; } catch(FWException &ex) { // address text line can not be converted to ipv4 address. // Since parsers do not understand ipv6 yet, assume this // is a host address and create DNSName object - ObjectSignature sig; - sig.type_name = DNSName::TYPENAME; - sig.dns_name = addr; - - if (deduplicate) - { - FWObject *obj = findMatchingObject(sig); - if (obj) return obj; - } name = addr; DNSName *da = DNSName::cast( - createObject(DNSName::TYPENAME, name.toStdString())); + ObjectMaker::createObject(DNSName::TYPENAME, name.toStdString())); da->setSourceName(addr.toStdString()); da->setRunTime(true); - registerObject(sig, da); return da; } } else { - ObjectSignature sig; - sig.type_name = Network::TYPENAME; - sig.address = addr; - sig.netmask = correct_nm; - - if (deduplicate) - { - FWObject *obj = findMatchingObject(sig); - if (obj) return obj; - } QString name = QString("net-") + addr + "/" + correct_nm; Network *net = Network::cast( - createObject(Network::TYPENAME, name.toStdString())); + ObjectMaker::createObject(Network::TYPENAME, name.toStdString())); try { net->setAddress( InetAddr(addr.toStdString()) ); @@ -154,37 +147,26 @@ FWObject* AddressObjectMaker::createAddress(const QString &addr, } } - registerObject(sig, net); - return net; } return NULL; } FWObject* AddressObjectMaker::createAddressRange(const QString &addr1, - const QString &addr2, - bool deduplicate) + const QString &addr2) { - ObjectSignature sig; - sig.type_name = AddressRange::TYPENAME; - sig.address_range_start = addr1; - sig.address_range_end = addr2; - if (deduplicate) - { - FWObject *obj = findMatchingObject(sig); - if (obj) return obj; - } QString name = QString("range-") + addr1 + "-" + addr2; AddressRange *ar = AddressRange::cast( - createObject(AddressRange::TYPENAME, name.toStdString())); + ObjectMaker::createObject(AddressRange::TYPENAME, name.toStdString())); try { ar->setRangeStart( InetAddr(addr1.toStdString()) ); } catch (FWException &ex) { - throw ObjectMakerException(QString("Error converting address '%1'").arg(addr1)); + throw ObjectMakerException( + QString("Error converting address '%1'").arg(addr1)); } try @@ -192,11 +174,10 @@ FWObject* AddressObjectMaker::createAddressRange(const QString &addr1, ar->setRangeEnd( InetAddr(addr2.toStdString()) ); } catch (FWException &ex) { - throw ObjectMakerException(QString("Error converting address '%1'").arg(addr2)); + throw ObjectMakerException( + QString("Error converting address '%1'").arg(addr2)); } - registerObject(sig, ar); - return ar; } diff --git a/src/import/addressObjectMaker.h b/src/import/addressObjectMaker.h index 1406b74d5..f968ae921 100644 --- a/src/import/addressObjectMaker.h +++ b/src/import/addressObjectMaker.h @@ -44,12 +44,13 @@ public: void setInvertedNetmasks(bool f) { inverted_netmasks = f; } + virtual libfwbuilder::FWObject* createObject(ObjectSignature &sig); + +protected: virtual libfwbuilder::FWObject* createAddress(const QString &a, - const QString &nm, - bool deduplicate=true); + const QString &nm); virtual libfwbuilder::FWObject* createAddressRange(const QString &a1, - const QString &a2, - bool deduplicate=true); + const QString &a2); }; diff --git a/src/import/objectMaker.cpp b/src/import/objectMaker.cpp index 402825943..237d5ffa5 100644 --- a/src/import/objectMaker.cpp +++ b/src/import/objectMaker.cpp @@ -50,11 +50,14 @@ #include "fwbuilder/FWOptions.h" #include "QStringListOperators.h" +#include "getProtoByName.h" +#include "getServByName.h" // TODO: FWBTree needs to be refactored into an independent module #include "../libgui/FWBTree.h" #include +#include #include @@ -65,14 +68,351 @@ using namespace libfwbuilder; using namespace std; -QString ObjectSignature::toString() const +QMap > ObjectSignature::icmp_names; + +ObjectSignature::ObjectSignature() +{ + protocol = 0; + + fragments = false; + short_fragments = false; + any_opt = false; + lsrr = false; + ssrr = false; + rr = false; + ts = false; + rtralt = false; + rtralt_value = false; + + icmp_type = -1; + icmp_code = -1; + + src_port_range_start = 0; + src_port_range_end = 0; + dst_port_range_start = 0; + dst_port_range_end = 0; + + established = false; +} + +ObjectSignature::ObjectSignature(const ObjectSignature &other) +{ + type_name = other.type_name; + object_name = other.object_name; + address = other.address; + netmask = other.netmask; + address_range_start = other.address_range_start; + address_range_end = other.address_range_end; + dns_name = other.dns_name; + address_table_name = other.address_table_name; + protocol = other.protocol; + fragments = other.fragments; + short_fragments = other.short_fragments; + any_opt = other.any_opt; + dscp = other.dscp; + tos = other.tos; + lsrr = other.lsrr; + ssrr = other.ssrr; + rr = other.rr; + ts = other.ts; + rtralt = other.rtralt; + rtralt_value = other.rtralt_value; + icmp_type = other.icmp_type; + icmp_code = other.icmp_code; + src_port_range_start = other.src_port_range_start; + src_port_range_end = other.src_port_range_end; + dst_port_range_start = other.dst_port_range_start; + dst_port_range_end = other.dst_port_range_end; + established = other.established; + flags_mask = other.flags_mask; + flags_comp = other.flags_comp; + platform = other.platform; + protocol_name = other.protocol_name; + code = other.code; + tag = other.tag; + + if (icmp_names.size() == 0) + { + // Cisco icmp names + icmp_names["echo-reply"] = QPair(0, 0); + icmp_names["unreachable"] = QPair(3, -1); // all "unreachables" + icmp_names["net-unreachable"] = QPair(3, 0); + icmp_names["host-unreachable"] = QPair(3, 1); + icmp_names["protocol-unreachable"] = QPair(3, 2); + icmp_names["port-unreachable"] = QPair(3, 3); + icmp_names["packet-too-big"] = QPair(3, 4); + icmp_names["source-route-failed"] = QPair(3, 5); + icmp_names["network-unknown"] = QPair(3, 6); + icmp_names["host-unknown"] = QPair(3, 7); + icmp_names["host-isolated"] = QPair(3, 8); + icmp_names["dod-net-prohibited"] = QPair(3, 9); + icmp_names["dod-host-prohibited"] = QPair(3, 10); + icmp_names["net-tos-unreachable"] = QPair(3, 11); + icmp_names["host-tos-unreachable"] = QPair(3, 12); + icmp_names["administratively-prohibited"] = QPair(3, 13); + icmp_names["host-precedence-unreachable"] = QPair(3, 14); + icmp_names["precedence-unreachable"] = QPair(3, 15); + icmp_names["source-quench"] = QPair(4, 0); + icmp_names["net-redirect"] = QPair(5, 0); + icmp_names["host-redirect"] = QPair(5, 1); + icmp_names["net-tos-redirect"] = QPair(5, 2); + icmp_names["host-tos-redirect"] = QPair(5, 3); + icmp_names["echo"] = QPair(8, 0); + icmp_names["router-advertisement"] = QPair(9, 0); + icmp_names["router-solicitation"] = QPair(10, 0); + icmp_names["ttl-exceeded"] = QPair(11, 0); + icmp_names["reassembly-timeout"] = QPair(11, 1); + icmp_names["general-parameter-problem"] = QPair(12, 0); + icmp_names["option-missing"] = QPair(12, 1); + icmp_names["timestamp-request"] = QPair(13, 0); + icmp_names["timestamp-reply"] = QPair(14, 0); + icmp_names["information-request"] = QPair(15, 0); + icmp_names["information-reply"] = QPair(16, 0); + icmp_names["mask-request"] = QPair(17, 0); + icmp_names["mask-reply"] = QPair(18, 0); + + // iptables icmp names + icmp_names["any"] = QPair(-1,-1); + icmp_names["echo-reply"] = QPair(0,0); + // all "unreachables" + icmp_names["destination-unreachable"] = QPair(3,-1); + icmp_names["network-unreachable"] = QPair(3,0); + icmp_names["host-unreachable"] = QPair(3,1); + icmp_names["protocol-unreachable"] = QPair(3,2); + icmp_names["port-unreachable"] = QPair(3,3); + icmp_names["fragmentation-needed"] = QPair(3,4); + icmp_names["source-route-failed"] = QPair(3,5); + icmp_names["network-unknown"] = QPair(3,6); + icmp_names["host-unknown"] = QPair(3,7); + icmp_names["host-isolated"] = QPair(3,8); + icmp_names["network-prohibited"] = QPair(3,9); + icmp_names["host-prohibited"] = QPair(3,10); + icmp_names["TOS-network-unreachable"] = QPair(3,11); + icmp_names["TOS-host-unreachable"] = QPair(3,12); + icmp_names["communication-prohibited"] = QPair(3,13); + icmp_names["host-precedence-violation"] = QPair(3,14); + icmp_names["precedence-cutoff"] = QPair(3,15); + icmp_names["source-quench"] = QPair(4,0); + icmp_names["redirect"] = QPair(5,-1); + icmp_names["network-redirect"] = QPair(5,0); + icmp_names["host-redirect"] = QPair(5,1); + icmp_names["TOS-network-redirect"] = QPair(5,2); + icmp_names["TOS-host-redirect"] = QPair(5,3); + icmp_names["echo-request"] = QPair(8,0); + icmp_names["router-advertisement"] = QPair(9,0); + icmp_names["router-solicitation"] = QPair(10,0); + icmp_names["ttl-exceeded"] = QPair(11,0); + icmp_names["time-exceeded"] = QPair(11,0); + icmp_names["ttl-zero-during-transit"] = QPair(11,0); + icmp_names["ttl-zero-during-reassembly"] = QPair(11,1); + icmp_names["parameter-problem"] = QPair(12,0); + icmp_names["ip-header-bad"] = QPair(12,0); + icmp_names["required-option-missing"] = QPair(12,1); + icmp_names["timestamp-request"] = QPair(13,0); + icmp_names["timestamp-reply"] = QPair(14,0); + icmp_names["information-request"] = QPair(15,0); + icmp_names["information-reply"] = QPair(16,0); + icmp_names["address-mask-request"] = QPair(17,0); + icmp_names["address-mask-reply"] = QPair(18,0); + + } +} + +void ObjectSignature::setProtocol(const QString &s) +{ + // this assumes protocol is represented by a number + bool ok = false; + protocol = QString(s).toInt(&ok); + if ( ! ok) + { + // could not convert protocol number + + protocol = GetProtoByName::getProtocolByName(s); + if (protocol == -1) + { + protocol = 0; + throw ObjectMakerException(QString("Protocol '%1' is unknown").arg(s)); + } + } +} + +void ObjectSignature::setIcmpFromName(const QString &s) +{ + if (icmp_names.count(s) > 0) + { + QPair p = icmp_names[s]; + icmp_type = p.first; + icmp_code = p.second; + } else + throw ObjectMakerException( + QString("ICMP service name '%1' is unknown").arg(s)); +} + +void ObjectSignature::setIcmpType(const QString &s) +{ + if (s.isEmpty()) icmp_type = -1; + else + { + bool ok = false; + icmp_type = s.toInt(&ok); + if (!ok) + { + // could not convert + icmp_type = -1; + throw ObjectMakerException(QString("ICMP type '%1' is unusable").arg(s)); + } + } +} + +void ObjectSignature::setIcmpCode(const QString &s) +{ + if (s.isEmpty()) icmp_code = -1; + else + { + bool ok = false; + icmp_code = s.toInt(&ok); + if (!ok) + { + // could not convert + icmp_code = -1; + throw ObjectMakerException(QString("ICMP code '%1' is unusable").arg(s)); + } + } +} + +int ObjectSignature::portFromString(const QString &port_spec, const QString &proto, + int default_port) +{ + QString ps = port_spec.trimmed(); + if (ps == "") return 0; + if (ps == ":") return default_port; + + int port = GetServByName::getPortByName(ps, proto); + if (port == -1) + { + throw ObjectMakerException(QString("Port name '%1' is unknown").arg(ps)); + port = 0; + } + return port; +} + +void ObjectSignature::setSrcPortRange(const QString &range_start_spec, + const QString &range_end_spec, + const QString &proto) +{ + src_port_range_start = portFromString(range_start_spec, proto, 0); + src_port_range_end = portFromString(range_end_spec, proto, 65535); +} + +void ObjectSignature::setDstPortRange(const QString &range_start_spec, + const QString &range_end_spec, + const QString &proto) +{ + dst_port_range_start = portFromString(range_start_spec, proto, 0); + dst_port_range_end = portFromString(range_end_spec, proto, 65535); +} + +/* + * Sets source port range from cisco-like port operation: + * + * eq www + * gt smtp + * lt 1024 + * range 10000 10010 + * + * @port_op is operation ("lt", "gt", "eq", "range") + * @port_spec is port number of service name + * @proto is protocol name used for GetServByName::GetPortByName() + */ +void ObjectSignature::setSrcPortRangeFromPortOp(const QString &port_op, + const QString &port_spec, + const QString &proto) +{ + QString portop = port_op.trimmed(); + QString portspec = port_spec.trimmed(); + + src_port_range_start = 0; + src_port_range_end = 0; + + QString range_start; + QString range_end; + QStringList sl = portspec.split(" "); + if (sl.size() > 1) + { + range_start = sl[0]; + range_end = sl[1]; + } else + { + range_start = portspec; + range_end = portspec; + } + + src_port_range_start = portFromString(range_start, proto, 0); + src_port_range_end = portFromString(range_end, proto, 65535); + + if (portop == "lt") src_port_range_start = 0; + if (portop=="gt") src_port_range_end = 65535; + if (portop=="eq") + { + src_port_range_start = src_port_range_end; + } + if (portop=="range") + { + // range_start and range_end have been set + ; + } +} + +void ObjectSignature::setDstPortRangeFromPortOp(const QString &port_op, + const QString &port_spec, + const QString &proto) +{ + QString portop = port_op.trimmed(); + QString portspec = port_spec.trimmed(); + + dst_port_range_start = 0; + dst_port_range_end = 0; + + QString range_start; + QString range_end; + QStringList sl = portspec.split(" "); + if (sl.size() > 1) + { + range_start = sl[0]; + range_end = sl[1]; + } else + { + range_start = portspec; + range_end = portspec; + } + + dst_port_range_start = portFromString(range_start, proto, 0); + dst_port_range_end = portFromString(range_end, proto, 65535); + + if (portop == "lt") dst_port_range_start = 0; + if (portop=="gt") dst_port_range_end = 65535; + if (portop=="eq") + { + dst_port_range_start = dst_port_range_end; + } + if (portop=="range") + { + // range_start and range_end have been set + ; + } +} + +QString ObjectSignature::ObjectSignature::toString() const { QStringList sig; sig << type_name; + if ( ! object_name.isEmpty()) sig << object_name; + if (type_name == IPv4::TYPENAME || type_name == IPv6::TYPENAME || - type_name == Network::TYPENAME || type_name == NetworkIPv6::TYPENAME) + type_name == Network::TYPENAME || type_name == NetworkIPv6::TYPENAME || + type_name == Address::TYPENAME) sig << address << netmask; if (type_name == AddressRange::TYPENAME) @@ -91,7 +431,18 @@ QString ObjectSignature::toString() const sig << icmp_type << icmp_code; if (type_name == IPService::TYPENAME) - sig << protocol << fragments; + sig << protocol + << fragments + << short_fragments + << any_opt + << dscp + << tos + << lsrr + << ssrr + << rr + << ts + << rtralt + << rtralt_value; if (type_name == TCPService::TYPENAME) sig << src_port_range_start << src_port_range_end @@ -106,11 +457,12 @@ QString ObjectSignature::toString() const if (type_name == TagService::TYPENAME) sig << tag; - return sig.join("|-|"); + return sig.join("| |"); } void* ObjectSignature::dispatch(Network *obj, void*) { + object_name = QString::fromUtf8(obj->getName().c_str()); type_name = obj->getTypeName().c_str(); address = obj->getAddressPtr()->toString().c_str(); netmask = obj->getNetmaskPtr()->toString().c_str(); @@ -119,6 +471,7 @@ void* ObjectSignature::dispatch(Network *obj, void*) void* ObjectSignature::dispatch(NetworkIPv6 *obj, void*) { + object_name = QString::fromUtf8(obj->getName().c_str()); type_name = obj->getTypeName().c_str(); address = obj->getAddressPtr()->toString().c_str(); netmask = obj->getNetmaskPtr()->toString().c_str(); @@ -127,6 +480,7 @@ void* ObjectSignature::dispatch(NetworkIPv6 *obj, void*) void* ObjectSignature::dispatch(IPv4 *obj, void*) { + object_name = QString::fromUtf8(obj->getName().c_str()); type_name = obj->getTypeName().c_str(); address = obj->getAddressPtr()->toString().c_str(); netmask = InetAddr::getAllOnes().toString().c_str(); @@ -135,6 +489,7 @@ void* ObjectSignature::dispatch(IPv4 *obj, void*) void* ObjectSignature::dispatch(IPv6 *obj, void*) { + object_name = QString::fromUtf8(obj->getName().c_str()); type_name = obj->getTypeName().c_str(); address = obj->getAddressPtr()->toString().c_str(); netmask = InetAddr::getAllOnes(AF_INET6).toString().c_str(); @@ -143,6 +498,7 @@ void* ObjectSignature::dispatch(IPv6 *obj, void*) void* ObjectSignature::dispatch(AddressRange *obj, void*) { + object_name = QString::fromUtf8(obj->getName().c_str()); type_name = obj->getTypeName().c_str(); address_range_start = obj->getRangeStart().toString().c_str(); address_range_end = obj->getRangeEnd().toString().c_str(); @@ -155,6 +511,7 @@ void* ObjectSignature::dispatch(AddressRange *obj, void*) */ void* ObjectSignature::dispatch(AddressTable *obj, void*) { + object_name = QString::fromUtf8(obj->getName().c_str()); type_name = obj->getTypeName().c_str(); address_table_name = obj->getSourceName().c_str(); return this; @@ -162,6 +519,7 @@ void* ObjectSignature::dispatch(AddressTable *obj, void*) void* ObjectSignature::dispatch(physAddress *obj, void*) { + object_name = QString::fromUtf8(obj->getName().c_str()); type_name = obj->getTypeName().c_str(); address = obj->getPhysAddress().c_str(); return this; @@ -169,14 +527,26 @@ void* ObjectSignature::dispatch(physAddress *obj, void*) void* ObjectSignature::dispatch(IPService *obj, void*) { + object_name = QString::fromUtf8(obj->getName().c_str()); type_name = obj->getTypeName().c_str(); protocol = obj->getProtocolNumber(); - fragments = obj->getBool("fragm") || obj->getBool("short_fragm"); + fragments = obj->getBool("fragm"); + short_fragments = obj->getBool("short_fragm"); + any_opt = obj->getBool("any_opt"); + dscp = obj->getStr("dscp").c_str(); + tos = obj->getStr("tos").c_str(); + lsrr = obj->getBool("lsrr"); + ssrr = obj->getBool("ssrr"); + rr = obj->getBool("rr"); + ts = obj->getBool("ts"); + rtralt = obj->getBool("rtralt"); + rtralt_value = obj->getBool("rtralt_value"); return this; } void* ObjectSignature::dispatch(ICMPService *obj, void*) { + object_name = QString::fromUtf8(obj->getName().c_str()); type_name = obj->getTypeName().c_str(); icmp_type = obj->getInt("type"); icmp_code = obj->getInt("code"); @@ -185,6 +555,7 @@ void* ObjectSignature::dispatch(ICMPService *obj, void*) void* ObjectSignature::dispatch(ICMP6Service *obj, void*) { + object_name = QString::fromUtf8(obj->getName().c_str()); type_name = obj->getTypeName().c_str(); icmp_type = obj->getInt("type"); icmp_code = obj->getInt("code"); @@ -193,6 +564,7 @@ void* ObjectSignature::dispatch(ICMP6Service *obj, void*) void* ObjectSignature::dispatch(TCPService *obj, void*) { + object_name = QString::fromUtf8(obj->getName().c_str()); type_name = obj->getTypeName().c_str(); src_port_range_start = obj->getSrcRangeStart(); src_port_range_end = obj->getSrcRangeEnd(); @@ -211,6 +583,7 @@ void* ObjectSignature::dispatch(TCPService *obj, void*) void* ObjectSignature::dispatch(UDPService *obj, void*) { + object_name = QString::fromUtf8(obj->getName().c_str()); type_name = obj->getTypeName().c_str(); src_port_range_start = obj->getSrcRangeStart(); src_port_range_end = obj->getSrcRangeEnd(); @@ -221,6 +594,7 @@ void* ObjectSignature::dispatch(UDPService *obj, void*) void* ObjectSignature::dispatch(CustomService *obj, void*) { + object_name = QString::fromUtf8(obj->getName().c_str()); type_name = obj->getTypeName().c_str(); platform = ""; code = ""; @@ -236,6 +610,7 @@ void* ObjectSignature::dispatch(CustomService *obj, void*) void* ObjectSignature::dispatch(TagService *obj, void*) { + object_name = QString::fromUtf8(obj->getName().c_str()); type_name = obj->getTypeName().c_str(); tag = obj->getStr("tagcode").c_str(); return this; @@ -247,6 +622,7 @@ void* ObjectSignature::dispatch(TagService *obj, void*) */ void* ObjectSignature::dispatch(DNSName *obj, void*) { + object_name = QString::fromUtf8(obj->getName().c_str()); type_name = obj->getTypeName().c_str(); dns_name = obj->getSourceName().c_str(); return this; @@ -258,20 +634,40 @@ void* ObjectSignature::dispatch(DNSName *obj, void*) void ObjectMaker::clear() { last_created = NULL; - object_registry.clear(); + named_object_registry.clear(); + anon_object_registry.clear(); } FWObject* ObjectMaker::findMatchingObject(const ObjectSignature &sig) { QString signature = sig.toString(); - if (object_registry.count(signature) > 0) - return library->getRoot()->findInIndex(object_registry[signature]); + if (named_object_registry.count(signature) > 0) + return library->getRoot()->findInIndex(named_object_registry[signature]); + + ObjectSignature anon_sig = sig; + anon_sig.object_name = ""; + QString anon_signature = anon_sig.toString(); + if (anon_object_registry.count(anon_signature) > 0) + return library->getRoot()->findInIndex(anon_object_registry[anon_signature]); + return NULL; } -void ObjectMaker::registerObject(const ObjectSignature &sig, FWObject* obj) +void ObjectMaker::registerNamedObject(const ObjectSignature &sig, FWObject* obj) { - object_registry[sig.toString()] = (obj!=NULL) ? obj->getId() : -1; + ObjectSignature anon_sig = sig; + anon_sig.object_name = ""; + QString as = anon_sig.toString(); + if (anon_object_registry.count(as) > 0) anon_object_registry.remove(as); + + named_object_registry[sig.toString()] = (obj!=NULL) ? obj->getId() : -1; +} + +void ObjectMaker::registerAnonymousObject(const ObjectSignature &sig, FWObject* obj) +{ + ObjectSignature anon_sig = sig; + anon_sig.object_name = ""; + anon_object_registry[anon_sig.toString()] = (obj!=NULL) ? obj->getId() : -1; } //**************************************************************** @@ -311,6 +707,11 @@ FWObject* ObjectMaker::createObject(FWObject *parent, return o; } +FWObject* ObjectMaker::createObject(ObjectSignature &) +{ + return NULL; +} + //**************************************************************** /* @@ -328,8 +729,11 @@ void ObjectMaker::prepareForDeduplication(FWObject *root) if (Address::cast(root) || Service::cast(root)) { ObjectSignature sig; + root->dispatch(&sig, (void*)(NULL)); - registerObject(sig, root); + + registerNamedObject(sig, root); + registerAnonymousObject(sig, root); // this erases sig.object_name } if (Library::isA(root) && root->getId() == FWObjectDatabase::DELETED_OBJECTS_ID) diff --git a/src/import/objectMaker.h b/src/import/objectMaker.h index 21102d3a9..5c605dbbc 100644 --- a/src/import/objectMaker.h +++ b/src/import/objectMaker.h @@ -30,6 +30,7 @@ #include #include +#include namespace libfwbuilder @@ -67,8 +68,14 @@ public: class ObjectSignature : public libfwbuilder::Dispatch { + static QMap > icmp_names; + public: + ObjectSignature(); + ObjectSignature(const ObjectSignature &other); + QString type_name; + QString object_name; // for address-like objects QString address; @@ -78,9 +85,21 @@ public: QString dns_name; QString address_table_name; - // for services + // for IP service int protocol; bool fragments; + bool short_fragments; + bool any_opt; + QString dscp; + QString tos; + bool lsrr; + bool ssrr; + bool rr; + bool ts; + bool rtralt; + bool rtralt_value; + + // for ICMP service int icmp_type; int icmp_code; @@ -103,6 +122,30 @@ public: // tag service QString tag; + // convenience methods that populate various attributes from + // strings taken from imported configs + void setProtocol(const QString &s); + void setIcmpFromName(const QString &s); + void setIcmpType(const QString &s); + void setIcmpCode(const QString &s); + + int portFromString(const QString &port_spec, const QString &proto, + int default_port); + + void setSrcPortRange(const QString &range_start_spec, + const QString &range_end_spec, + const QString &proto); + void setDstPortRange(const QString &range_start_spec, + const QString &range_end_spec, + const QString &proto); + + void setSrcPortRangeFromPortOp(const QString &port_op, + const QString &port_spec, + const QString &proto); + void setDstPortRangeFromPortOp(const QString &port_op, + const QString &port_spec, + const QString &proto); + QString toString() const; // The following methods build signature from given object taking @@ -127,10 +170,18 @@ public: class ObjectMaker { +protected: libfwbuilder::Library *library; libfwbuilder::FWObject *last_created; - QMap object_registry; + QMap named_object_registry; + QMap anon_object_registry; + + libfwbuilder::FWObject* findMatchingObject(const ObjectSignature &sig); + void registerNamedObject(const ObjectSignature &sig, + libfwbuilder::FWObject* obj); + void registerAnonymousObject(const ObjectSignature &sig, + libfwbuilder::FWObject* obj); public: @@ -139,8 +190,11 @@ public: virtual void clear(); - libfwbuilder::FWObject* findMatchingObject(const ObjectSignature &sig); - void registerObject(const ObjectSignature &sig, libfwbuilder::FWObject* obj); + virtual libfwbuilder::FWObject* createObject(ObjectSignature &sig); + + libfwbuilder::FWObject *getLastCreatedObject() { return last_created; } + + void prepareForDeduplication(libfwbuilder::FWObject *root); libfwbuilder::FWObject* createObject(const std::string &objType, const std::string &objName); @@ -148,11 +202,7 @@ public: libfwbuilder::FWObject* createObject(libfwbuilder::FWObject *parent, const std::string &objType, const std::string &objName); - - libfwbuilder::FWObject *getLastCreatedObject() { return last_created; } - void prepareForDeduplication(libfwbuilder::FWObject *root); - }; #endif diff --git a/src/import/serviceObjectMaker.cpp b/src/import/serviceObjectMaker.cpp index 202472601..87b3f6bb5 100644 --- a/src/import/serviceObjectMaker.cpp +++ b/src/import/serviceObjectMaker.cpp @@ -35,6 +35,7 @@ #include "QStringListOperators.h" #include +#include extern int fwbdebug; @@ -60,7 +61,7 @@ ServiceObjectMaker::ServiceObjectMaker(Library *l) : ObjectMaker(l) sig.type_name = IPService::TYPENAME; sig.protocol = 0; sig.fragments = false; - registerObject(sig, NULL); // "any" + registerAnonymousObject(sig, NULL); // "any" } ServiceObjectMaker::~ServiceObjectMaker() {} @@ -70,23 +71,77 @@ void ServiceObjectMaker::clear() ObjectMaker::clear(); } -FWObject* ServiceObjectMaker::getCustomService(const QString &platform, - const QString &code, - const QString &protocol, - bool deduplicate) +FWObject* ServiceObjectMaker::createObject(ObjectSignature &sig) { - ObjectSignature sig; - sig.type_name = CustomService::TYPENAME; - sig.platform = platform; - sig.protocol_name = protocol; - sig.code = code; + assert( ! sig.type_name.isEmpty()); - if (deduplicate) + FWObject *obj = findMatchingObject(sig); + + // qDebug() << "Create object " << sig.toString() + // << " obj=" << obj; + + if (obj) return obj; + + if (sig.type_name == CustomService::TYPENAME) + obj = getCustomService(sig.platform, sig.code, sig.protocol_name); + + if (sig.type_name == IPService::TYPENAME) { - FWObject *obj = findMatchingObject(sig); - if (obj) return obj; + QString name; + if (sig.protocol > 0) name = QString("ip-%1").arg(sig.protocol); + else name = "ip"; + if (sig.fragments) name += "-fragm"; + obj = ObjectMaker::createObject(IPService::TYPENAME, name.toStdString()); + obj->setInt("protocol_num", sig.protocol); + obj->setBool("fragm", sig.fragments); + obj->setBool("short_fragm", sig.short_fragments); + obj->setBool("any_opt", sig.any_opt); + obj->setStr("dscp", sig.dscp.toStdString()); + obj->setStr("tos", sig.tos.toStdString()); + obj->setBool("lsrr", sig.lsrr); + obj->setBool("ssrr", sig.ssrr); + obj->setBool("rr", sig.rr); + obj->setBool("ts", sig.ts); + obj->setBool("rtralt", sig.rtralt); + obj->setBool("rtralt_value", sig.rtralt_value); } + if (sig.type_name == ICMPService::TYPENAME) + { + QString name = QString("icmp %1/%2").arg(sig.icmp_type).arg(sig.icmp_code); + obj = ObjectMaker::createObject(ICMPService::TYPENAME, name.toStdString()); + obj->setInt("type", sig.icmp_type); + obj->setInt("code", sig.icmp_code); + } + + if (sig.type_name == TCPService::TYPENAME) + obj = getTCPService(sig.src_port_range_start, sig.src_port_range_end, + sig.dst_port_range_start, sig.dst_port_range_end, + sig.established, + sig.flags_mask, + sig.flags_comp); + + if (sig.type_name == UDPService::TYPENAME) + obj = getUDPService(sig.src_port_range_start, sig.src_port_range_end, + sig.dst_port_range_start, sig.dst_port_range_end); + + if (sig.type_name == TagService::TYPENAME) + obj = getTagService(sig.tag); + + if ( ! sig.object_name.isEmpty()) + { + obj->setName(sig.object_name.toUtf8().constData()); + registerNamedObject(sig, obj); + } else + registerAnonymousObject(sig, obj); + + return obj; +} + +FWObject* ServiceObjectMaker::getCustomService(const QString &platform, + const QString &code, + const QString &protocol) +{ QString custom_service_name_sig = platform + "-" + code; if (custom_service_codes.count(custom_service_name_sig) > 0) custom_service_code_tracker++; @@ -96,63 +151,9 @@ FWObject* ServiceObjectMaker::getCustomService(const QString &platform, if ( ! protocol.isEmpty()) name << "-" << protocol; CustomService *s = CustomService::cast( - createObject(CustomService::TYPENAME, name.join("").toStdString())); + ObjectMaker::createObject(CustomService::TYPENAME, name.join("").toStdString())); if (!protocol.isEmpty()) s->setProtocol(protocol.toStdString()); s->setCodeForPlatform(platform.toStdString(), code.toStdString()); - - registerObject(sig, s); - - return s; -} - -FWObject* ServiceObjectMaker::getIPService(int proto, bool fragments, - bool deduplicate) -{ - ObjectSignature sig; - sig.type_name = IPService::TYPENAME; - sig.protocol = proto; - sig.fragments = fragments; - - if (deduplicate) - { - FWObject *obj = findMatchingObject(sig); - if (obj) return obj; - } - - QString name = QString("ip-%1").arg(proto); - if (fragments) name += "-frag"; - IPService *s = IPService::cast( - createObject(IPService::TYPENAME, name.toStdString())); - s->setInt("protocol_num", proto); - s->setBool("fragm", fragments); - - registerObject(sig, s); - - return s; -} - -FWObject* ServiceObjectMaker::getICMPService(int type, int code, bool deduplicate) -{ - ObjectSignature sig; - sig.type_name = ICMPService::TYPENAME; - sig.icmp_type = type; - sig.icmp_code = code; - - if (deduplicate) - { - FWObject *obj = findMatchingObject(sig); - if (obj) return obj; - } - - QString name = QString("icmp %1/%2").arg(type).arg(code); - - ICMPService *s = ICMPService::cast( - createObject(ICMPService::TYPENAME, name.toStdString())); - s->setInt("type", type); - s->setInt("code", code); - - registerObject(sig, s); - return s; } @@ -160,25 +161,8 @@ FWObject* ServiceObjectMaker::getTCPService(int srs, int sre, int drs, int dre, bool established, QList &flags_mask, - QList &flags_comp, - bool deduplicate) + QList &flags_comp) { - ObjectSignature sig; - sig.type_name = TCPService::TYPENAME; - sig.src_port_range_start = srs; - sig.src_port_range_end = sre; - sig.dst_port_range_start = drs; - sig.dst_port_range_end = dre; - sig.established = established; - sig.flags_mask = flags_mask; - sig.flags_comp = flags_comp; - - if (deduplicate) - { - FWObject *obj = findMatchingObject(sig); - if (obj) return obj; - } - QStringList nl; nl << QString("tcp %1:%2 / %3:%4").arg(srs).arg(sre).arg(drs).arg(dre); @@ -193,7 +177,7 @@ FWObject* ServiceObjectMaker::getTCPService(int srs, int sre, } TCPService* s = TCPService::cast( - createObject(TCPService::TYPENAME, nl.join(" ").toStdString())); + ObjectMaker::createObject(TCPService::TYPENAME, nl.join(" ").toStdString())); s->setSrcRangeStart(srs); s->setSrcRangeEnd(sre); s->setDstRangeStart(drs); @@ -240,65 +224,35 @@ FWObject* ServiceObjectMaker::getTCPService(int srs, int sre, s->setEstablished(established); - registerObject(sig, s); - return s; } -FWObject* ServiceObjectMaker::getUDPService(int srs, int sre, int drs, int dre, - bool deduplicate) +FWObject* ServiceObjectMaker::getUDPService(int srs, int sre, int drs, int dre) { - ObjectSignature sig; - sig.type_name = UDPService::TYPENAME; - sig.src_port_range_start = srs; - sig.src_port_range_end = sre; - sig.dst_port_range_start = drs; - sig.dst_port_range_end = dre; - - if (deduplicate) - { - FWObject *obj = findMatchingObject(sig); - if (obj) return obj; - } - QString name = QString("udp %1:%2 / %3:%4") .arg(srs).arg(sre).arg(drs).arg(dre); UDPService* s = UDPService::cast( - createObject(UDPService::TYPENAME, name.toStdString())); + ObjectMaker::createObject(UDPService::TYPENAME, name.toStdString())); s->setSrcRangeStart(srs); s->setSrcRangeEnd(sre); s->setDstRangeStart(drs); s->setDstRangeEnd(dre); - registerObject(sig, s); - return s; } -FWObject* ServiceObjectMaker::getTagService(const QString &tagcode, - bool deduplicate) +FWObject* ServiceObjectMaker::getTagService(const QString &tagcode) { - ObjectSignature sig; - sig.type_name = TagService::TYPENAME; - sig.tag = tagcode; - - if (deduplicate) - { - FWObject *obj = findMatchingObject(sig); - if (obj) return obj; - } - TagService *s = NULL; QString name = QString("tag-%1").arg(tagcode); - s = TagService::cast(createObject(TagService::TYPENAME, name.toStdString())); + s = TagService::cast( + ObjectMaker::createObject(TagService::TYPENAME, name.toStdString())); assert(s!=NULL); s->setCode(tagcode.toStdString()); - registerObject(sig, s); - return s; } diff --git a/src/import/serviceObjectMaker.h b/src/import/serviceObjectMaker.h index 0e7134089..610d96eda 100644 --- a/src/import/serviceObjectMaker.h +++ b/src/import/serviceObjectMaker.h @@ -40,29 +40,24 @@ public: virtual ~ServiceObjectMaker(); virtual void clear(); - + + virtual libfwbuilder::FWObject* createObject(ObjectSignature &sig); + +protected: virtual libfwbuilder::FWObject* getCustomService(const QString &platform, const QString &code, - const QString &protocol, - bool deduplicate=true); - virtual libfwbuilder::FWObject* getIPService(int proto, bool fragments, - bool deduplicate=true); - virtual libfwbuilder::FWObject* getICMPService(int type, int code, - bool deduplicate=true); + const QString &protocol); virtual libfwbuilder::FWObject* getTCPService(int srs, int sre, int drs, int dre, bool established, QList &flags_mask, - QList &flags_comp, - bool deduplicate=true); + QList &flags_comp); virtual libfwbuilder::FWObject* getUDPService(int srs, int sre, - int drs, int dre, - bool deduplicate=true); + int drs, int dre); - virtual libfwbuilder::FWObject* getTagService(const QString &tagcode, - bool deduplicate=true); + virtual libfwbuilder::FWObject* getTagService(const QString &tagcode); diff --git a/src/unit_tests/ImporterTest/test_data/ios.fwb b/src/unit_tests/ImporterTest/test_data/ios.fwb index 025ca8e2a..5faddbab5 100644 --- a/src/unit_tests/ImporterTest/test_data/ios.fwb +++ b/src/unit_tests/ImporterTest/test_data/ios.fwb @@ -1,6 +1,6 @@ - + @@ -467,10 +467,10 @@ - - - - + + + + diff --git a/src/unit_tests/ImporterTest/test_data/ipt.fwb b/src/unit_tests/ImporterTest/test_data/ipt.fwb index db240db43..931f5ef71 100644 --- a/src/unit_tests/ImporterTest/test_data/ipt.fwb +++ b/src/unit_tests/ImporterTest/test_data/ipt.fwb @@ -1,6 +1,6 @@ - + @@ -511,7 +511,7 @@ - + @@ -537,7 +537,7 @@ - + @@ -1675,7 +1675,7 @@ - + @@ -1693,11 +1693,10 @@ - - + @@ -1715,7 +1714,6 @@ - @@ -2512,7 +2510,7 @@ - + @@ -2529,7 +2527,6 @@ - diff --git a/src/unit_tests/ImporterTest/test_data/ipt.test b/src/unit_tests/ImporterTest/test_data/ipt.test index a7a2cc01b..20d27b5ad 100644 --- a/src/unit_tests/ImporterTest/test_data/ipt.test +++ b/src/unit_tests/ImporterTest/test_data/ipt.test @@ -65,9 +65,9 @@ -A INPUT -p udp --dport 0:8000 -j REJECT --reject-with icmp-admin-prohibited -A INPUT -p udp --dport 0:8000 -j REJECT --reject-with admin-prohib -# and lets try something we can not parse to make sure error is issued --A INPUT -p udp --dport 0:8000 -j REJECT --reject-with icmp-foo-prohibited --A INPUT -p udp --dport 0:8000 -j REJECT --reject-with foo-prohib +# was: bad --reject-with argument +-A INPUT -p udp --dport 0:8000 -j REJECT --reject-with icmp-admin-prohibited +-A INPUT -p udp --dport 0:8000 -j REJECT --reject-with admin-prohib # v2.1 does not support passing control to the same branch from @@ -146,8 +146,8 @@ -A scan_checks_chain -i eth0 -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP -# bad port spec --A user_chain -s 192.168.0.0/16 -p tcp -m tcp --dport foo -m state --state NEW -j ACCEPT +# was: bad port spec +-A user_chain -s 192.168.0.0/16 -p tcp -m tcp --dport 8088 -m state --state NEW -j ACCEPT # Log prefix and log limit test # Also need action Continue (or NOP)