From 2ba7dc48a803744ce74013da24ebf76f7c839962 Mon Sep 17 00:00:00 2001 From: RomanKubiak Date: Thu, 23 Jul 2015 14:31:43 +0200 Subject: [PATCH 01/16] Switched all enums to "enum class : uint8_t" types Change-Id: I0c24cb67e2cb362a2c1970edca6f1947e05b806a --- include/nether_PolicyBackend.h | 2 +- include/nether_Types.h | 23 +++++++-------- include/nether_Utils.h | 64 +++++++++++++++++++++--------------------- src/nether_CynaraBackend.cpp | 12 ++++---- src/nether_Main.cpp | 8 +++--- src/nether_Manager.cpp | 10 +++---- src/nether_Netlink.cpp | 6 ++-- src/nether_NetworkUtils.cpp | 32 ++++++++++----------- 8 files changed, 79 insertions(+), 78 deletions(-) diff --git a/include/nether_PolicyBackend.h b/include/nether_PolicyBackend.h index dc9ecd6..4d2145f 100644 --- a/include/nether_PolicyBackend.h +++ b/include/nether_PolicyBackend.h @@ -38,7 +38,7 @@ class NetherPolicyBackend : public NetherVerdictCaster virtual const bool reload() { return (true); }; virtual const bool isValid() = 0; virtual const int getDescriptor() { return (-1); } - virtual const NetherDescriptorStatus getDescriptorStatus() { return (unknownStatus); } + virtual const NetherDescriptorStatus getDescriptorStatus() { return (NetherDescriptorStatus::unknownStatus); } virtual const bool processEvents() = 0; protected: diff --git a/include/nether_Types.h b/include/nether_Types.h index 1e67a0b..8802b47 100644 --- a/include/nether_Types.h +++ b/include/nether_Types.h @@ -30,10 +30,11 @@ #include #include #include -#include #include +#include #include +#include #include #include #include @@ -62,14 +63,14 @@ #endif // HAVE_SYSTEMD_JOURNAL #if defined(HAVE_CYNARA) - #define NETHER_PRIMARY_BACKEND cynaraBackend - #define NETHER_BACKUP_BACKEND fileBackend + #define NETHER_PRIMARY_BACKEND NetherPolicyBackendType::cynaraBackend + #define NETHER_BACKUP_BACKEND NetherPolicyBackendType::fileBackend #else #define NETHER_PRIMARY_BACKEND fileBackend #define NETHER_BACKUP_BACKEND dummyBackend #endif // HAVE_CYNARA -#define NETHER_DEFAULT_VERDICT allowAndLog +#define NETHER_DEFAULT_VERDICT NetherVerdict::allowAndLog #define NETHER_PACKET_BUFFER_SIZE 4096 #define NETHER_INVALID_UID (uid_t) -1 #define NETHER_INVALID_GID (gid_t) -1 @@ -79,7 +80,7 @@ #define NETHER_MAX_USER_LEN 32 #define NETLINK_DROP_MARK 3 #define NETLINK_ALLOWLOG_MARK 4 -#define NETHER_LOG_BACKEND stderrBackend +#define NETHER_LOG_BACKEND NetherLogBackendType::stderrBackend #define NETHER_IPTABLES_RESTORE_PATH "/usr/sbin/iptables-restore" #ifndef NETHER_RULES_PATH #define NETHER_RULES_PATH "/etc/nether/nether.rules" @@ -89,14 +90,14 @@ #define NETHER_POLICY_FILE "/etc/nether/nether.policy" #endif // NETHER_POLICY_FILE -enum NetherPolicyBackendType +enum class NetherPolicyBackendType : std::uint8_t { cynaraBackend, fileBackend, dummyBackend }; -enum NetherLogBackendType +enum class NetherLogBackendType : std::uint8_t { stderrBackend, syslogBackend, @@ -105,7 +106,7 @@ enum NetherLogBackendType nullBackend }; -enum NetherVerdict +enum class NetherVerdict : std::uint8_t { allow, allowAndLog, @@ -113,7 +114,7 @@ enum NetherVerdict noVerdictYet }; -enum NetherDescriptorStatus +enum class NetherDescriptorStatus : std::uint8_t { readOnly, writeOnly, @@ -121,7 +122,7 @@ enum NetherDescriptorStatus unknownStatus }; -enum NetherTransportType +enum class NetherTransportType : std::uint8_t { TCP, UDP, @@ -130,7 +131,7 @@ enum NetherTransportType unknownTransportType }; -enum NetherProtocolType +enum class NetherProtocolType : std::uint8_t { IPv4, IPv6, diff --git a/include/nether_Utils.h b/include/nether_Utils.h index 8fe6e28..7298a5c 100644 --- a/include/nether_Utils.h +++ b/include/nether_Utils.h @@ -41,56 +41,56 @@ static const NetherVerdict stringToVerdict (char *verdictAsString) if (verdictAsString) { if (strncasecmp (verdictAsString, "allow_log", 9) == 0) - return (allowAndLog); + return (NetherVerdict::allowAndLog); if (strncasecmp (verdictAsString, "allow", 6) == 0) - return (allow); + return (NetherVerdict::allow); if (strncasecmp (verdictAsString, "deny", 4) == 0) - return (deny); + return (NetherVerdict::deny); } - return (allowAndLog); + return (NetherVerdict::allowAndLog); } static const NetherPolicyBackendType stringToBackendType (char *backendAsString) { if (strcasecmp (backendAsString, "cynara") == 0) - return (cynaraBackend); + return (NetherPolicyBackendType::cynaraBackend); if (strcasecmp (backendAsString, "file") == 0) - return (fileBackend); + return (NetherPolicyBackendType::fileBackend); if (strcasecmp (backendAsString, "dummy") == 0) - return (dummyBackend); + return (NetherPolicyBackendType::dummyBackend); - return (dummyBackend); + return (NetherPolicyBackendType::dummyBackend); } static const NetherLogBackendType stringToLogBackendType(char *backendAsString) { if (strcasecmp (backendAsString, "stderr") == 0) - return (stderrBackend); + return (NetherLogBackendType::stderrBackend); if (strcasecmp (backendAsString, "syslog") == 0) - return (syslogBackend); + return (NetherLogBackendType::syslogBackend); if (strcasecmp (backendAsString, "journal") == 0) - return (journalBackend); + return (NetherLogBackendType::journalBackend); if (strcasecmp (backendAsString, "file") == 0) - return (logfileBackend); + return (NetherLogBackendType::logfileBackend); if (strcasecmp (backendAsString, "null") == 0) - return (nullBackend); + return (NetherLogBackendType::nullBackend); - return (nullBackend); + return (NetherLogBackendType::nullBackend); } static const std::string logBackendTypeToString(const NetherLogBackendType backendType) { switch (backendType) { - case stderrBackend: + case NetherLogBackendType::stderrBackend: return ("stderr"); - case syslogBackend: + case NetherLogBackendType::syslogBackend: return ("syslog"); - case journalBackend: + case NetherLogBackendType::journalBackend: return ("journal"); - case logfileBackend: + case NetherLogBackendType::logfileBackend: return ("file"); - case nullBackend: + case NetherLogBackendType::nullBackend: return ("null"); } return ("null"); @@ -100,11 +100,11 @@ static const std::string backendTypeToString (const NetherPolicyBackendType back { switch (backendType) { - case cynaraBackend: + case NetherPolicyBackendType::cynaraBackend: return ("cynara"); - case fileBackend: + case NetherPolicyBackendType::fileBackend: return ("file"); - case dummyBackend: + case NetherPolicyBackendType::dummyBackend: default: return ("dummy"); } @@ -114,11 +114,11 @@ static const std::string verdictToString (const NetherVerdict verdict) { switch (verdict) { - case allow: + case NetherVerdict::allow: return ("ALLOW"); - case allowAndLog: + case NetherVerdict::allowAndLog: return ("ALLOW_LOG"); - case deny: + case NetherVerdict::deny: return ("DENY"); } } @@ -127,15 +127,15 @@ static const std::string transportToString(const NetherTransportType transportTy { switch (transportType) { - case TCP: + case NetherTransportType::TCP: return ("TCP"); - case UDP: + case NetherTransportType::UDP: return ("UDP"); - case ICMP: + case NetherTransportType::ICMP: return ("ICMP"); - case IGMP: + case NetherTransportType::IGMP: return ("IGMP"); - case unknownTransportType: + case NetherTransportType::unknownTransportType: default: return ("UNKNOWN"); } @@ -145,9 +145,9 @@ static const std::string protocolToString(const NetherProtocolType protocolType) { switch (protocolType) { - case IPv4: + case NetherProtocolType::IPv4: return ("IPv4"); - case IPv6: + case NetherProtocolType::IPv6: return ("IPv6"); default: return ("UNKNOWN"); diff --git a/src/nether_CynaraBackend.cpp b/src/nether_CynaraBackend.cpp index 997a553..589387c 100644 --- a/src/nether_CynaraBackend.cpp +++ b/src/nether_CynaraBackend.cpp @@ -54,10 +54,10 @@ void NetherCynaraBackend::statusCallback(int oldFd, int newFd, cynara_async_stat NetherCynaraBackend *backend = static_cast(data); if (status == CYNARA_STATUS_FOR_READ) - backend->setCynaraDescriptor(newFd, readOnly); + backend->setCynaraDescriptor(newFd, NetherDescriptorStatus::readOnly); if (status == CYNARA_STATUS_FOR_RW) - backend->setCynaraDescriptor(newFd, readWrite); + backend->setCynaraDescriptor(newFd, NetherDescriptorStatus::readWrite); } void NetherCynaraBackend::checkCallback(cynara_check_id check_id, @@ -88,11 +88,11 @@ const bool NetherCynaraBackend::enqueueVerdict (const NetherPacket &packet) { case CYNARA_API_ACCESS_ALLOWED: LOGD(cynaraErrorCodeToString(cynaraLastResult).c_str()); - return (castVerdict(packet, allow)); + return (castVerdict(packet, NetherVerdict::allow)); case CYNARA_API_ACCESS_DENIED: LOGD(cynaraErrorCodeToString(cynaraLastResult).c_str()); - return (castVerdict(packet, deny)); + return (castVerdict(packet, NetherVerdict::deny)); case CYNARA_API_CACHE_MISS: cynaraLastResult = cynara_async_create_request(cynaraContext, @@ -136,9 +136,9 @@ void NetherCynaraBackend::setCynaraVerdict(cynara_check_id checkId, int cynaraRe responseQueue[checkId] = -1; if (cynaraResult == CYNARA_API_ACCESS_ALLOWED) - castVerdict (packetId, allow); + castVerdict (packetId, NetherVerdict::allow); else - castVerdict (packetId, deny); + castVerdict (packetId, NetherVerdict::deny); return; } diff --git a/src/nether_Main.cpp b/src/nether_Main.cpp index 66d6d5b..8914a20 100644 --- a/src/nether_Main.cpp +++ b/src/nether_Main.cpp @@ -152,17 +152,17 @@ int main(int argc, char *argv[]) } switch (netherConfig.logBackend) { - case stderrBackend: + case NetherLogBackendType::stderrBackend: logger::Logger::setLogBackend (new logger::StderrBackend(false)); break; - case syslogBackend: + case NetherLogBackendType::syslogBackend: logger::Logger::setLogBackend (new logger::SyslogBackend()); break; - case logfileBackend: + case NetherLogBackendType::logfileBackend: logger::Logger::setLogBackend (new logger::FileBackend(netherConfig.logBackendArgs)); break; #if defined(HAVE_SYSTEMD_JOURNAL) - case journalBackend: + case NetherLogBackendType::journalBackend: logger::Logger::setLogBackend (new logger::SystemdJournalBackend()); break; #endif diff --git a/src/nether_Manager.cpp b/src/nether_Manager.cpp index 53e039a..581296a 100644 --- a/src/nether_Manager.cpp +++ b/src/nether_Manager.cpp @@ -236,11 +236,11 @@ void NetherManager::setupSelectSockets(fd_set &watchedReadDescriptorsSet, fd_set if ((backendDescriptor = netherPrimaryPolicyBackend->getDescriptor()) >= 0) { - if (netherPrimaryPolicyBackend->getDescriptorStatus() == readOnly) + if (netherPrimaryPolicyBackend->getDescriptorStatus() == NetherDescriptorStatus::readOnly) { FD_SET(backendDescriptor, &watchedReadDescriptorsSet); } - else if (netherPrimaryPolicyBackend->getDescriptorStatus() == readWrite) + else if (netherPrimaryPolicyBackend->getDescriptorStatus() == NetherDescriptorStatus::readWrite) { FD_SET(backendDescriptor, &watchedReadDescriptorsSet); FD_SET(backendDescriptor, &watchedWriteDescriptorsSet); @@ -260,15 +260,15 @@ NetherPolicyBackend *NetherManager::getPolicyBackend(const NetherConfig &netherC { switch (primary ? netherConfig.primaryBackendType : netherConfig.backupBackendType) { - case cynaraBackend: + case NetherPolicyBackendType::cynaraBackend: #ifdef HAVE_CYNARA return new NetherCynaraBackend(netherConfig); #else return new NetherDummyBackend(netherConfig); #endif - case fileBackend: + case NetherPolicyBackendType::fileBackend: return new NetherFileBackend(netherConfig); - case dummyBackend: + case NetherPolicyBackendType::dummyBackend: default: return new NetherDummyBackend(netherConfig); } diff --git a/src/nether_Netlink.cpp b/src/nether_Netlink.cpp index 65f6bee..1b98bfa 100644 --- a/src/nether_Netlink.cpp +++ b/src/nether_Netlink.cpp @@ -159,11 +159,11 @@ void NetherNetlink::setVerdict(const u_int32_t packetId, const NetherVerdict ver int ret = 0; LOGD("id=" << packetId << " verdict=" << verdictToString(verdict)); - if (verdict == allow) + if (verdict == NetherVerdict::allow) ret = nfq_set_verdict (queueHandle, packetId, NF_ACCEPT, 0, NULL); - if (verdict == deny) + if (verdict == NetherVerdict::deny) ret = nfq_set_verdict2 (queueHandle, packetId, NF_ACCEPT, netherConfig.markDeny, 0, NULL); - if (verdict == allowAndLog) + if (verdict == NetherVerdict::allowAndLog) ret = nfq_set_verdict2 (queueHandle, packetId, NF_ACCEPT, netherConfig.markAllowAndLog, 0, NULL); if (ret == -1) diff --git a/src/nether_NetworkUtils.cpp b/src/nether_NetworkUtils.cpp index 8b7db5c..8fbe8fa 100644 --- a/src/nether_NetworkUtils.cpp +++ b/src/nether_NetworkUtils.cpp @@ -43,16 +43,16 @@ void decodePacket(NetherPacket &packet, unsigned char *payload) switch(ipVersion) { case 4: - packet.protocolType = IPv4; + packet.protocolType = NetherProtocolType::IPv4; decodeIPv4Packet(packet, payload); break; case 6: - packet.protocolType = IPv6; + packet.protocolType = NetherProtocolType::IPv6; decodeIPv6Packet(packet, payload); break; default: - packet.transportType = unknownTransportType; - packet.protocolType = unknownProtocolType; + packet.transportType = NetherTransportType::unknownTransportType; + packet.protocolType = NetherProtocolType::unknownProtocolType; break; } } @@ -70,21 +70,21 @@ void decodeIPv6Packet(NetherPacket &packet, unsigned char *payload) switch(nextProto) { case IP_PROTOCOL_UDP: - packet.transportType = UDP; + packet.transportType = NetherTransportType::UDP; decodeUdp(packet, &payload[startOfIpPayload]); break; case IP_PROTOCOL_TCP: - packet.transportType = TCP; + packet.transportType = NetherTransportType::TCP; decodeTcp(packet, &payload[startOfIpPayload]); break; case IP_PROTOCOL_ICMP: - packet.transportType = ICMP; + packet.transportType = NetherTransportType::ICMP; break; case IP_PROTOCOL_IGMP: - packet.transportType = IGMP; + packet.transportType = NetherTransportType::IGMP; break; default: - packet.transportType = unknownTransportType; + packet.transportType = NetherTransportType::unknownTransportType; break; } } @@ -104,20 +104,20 @@ void decodeIPv4Packet(NetherPacket &packet, unsigned char *payload) switch(nextProto) { case IP_PROTOCOL_UDP: - packet.transportType = UDP; + packet.transportType = NetherTransportType::UDP; decodeUdp(packet, &payload[startOfIpPayload]); break; case IP_PROTOCOL_TCP: - packet.transportType = TCP; + packet.transportType = NetherTransportType::TCP; decodeTcp(packet, &payload[startOfIpPayload]); break; case IP_PROTOCOL_ICMP: - packet.transportType = ICMP; + packet.transportType = NetherTransportType::ICMP; break; case IP_PROTOCOL_IGMP: - packet.transportType = IGMP; + packet.transportType = NetherTransportType::IGMP; default: - packet.transportType = unknownTransportType; + packet.transportType = NetherTransportType::unknownTransportType; break; } } @@ -139,9 +139,9 @@ const std::string ipAddressToString(const char *src, enum NetherProtocolType typ { switch(type) { - case IPv4: + case NetherProtocolType::IPv4: return (stringFormat("%u.%u.%u.%u", src[0]&0xff,src[1]&0xff,src[2]&0xff,src[3]&0xff)); - case IPv6: + case NetherProtocolType::IPv6: return (stringFormat("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", ntohs(*(uint16_t*) &src[0]), ntohs(*(uint16_t*) &src[2]), ntohs(*(uint16_t*) &src[4]), ntohs(*(uint16_t*) &src[6]), -- 2.7.4 From 2c8d840707aeaa03226158898e7dc49c6cac45e5 Mon Sep 17 00:00:00 2001 From: RomanKubiak Date: Fri, 24 Jul 2015 15:14:34 +0200 Subject: [PATCH 02/16] Fixed EOLs/TABs/spaces Included fixes and changes from change I16970c3dedd9071c970523a478fbf35e009d13ef as commented by Jan Olszak and Rafal Krypa refer to https://review.tizen.org/gerrit/#/c/44086/ for details Removed const qualifiers on method return types. Removed unused parameters from method definitions. Change-Id: Ic03f4b35cdb476005749d2c93a413a83c09490fd --- CMakeLists.txt | 9 +- include/logger/backend-file.hpp | 26 +- include/logger/backend-journal.hpp | 26 +- include/logger/backend-null.hpp | 26 +- include/logger/backend-stderr.hpp | 32 ++- include/logger/backend-syslog.hpp | 20 +- include/logger/backend.hpp | 30 +- include/logger/ccolor.hpp | 43 +-- include/logger/formatter.hpp | 32 ++- include/logger/level.hpp | 46 ++-- include/logger/logger-scope.hpp | 69 ++--- include/logger/logger.hpp | 32 ++- include/nether_CynaraBackend.h | 49 ++-- include/nether_Daemon.h | 82 +++--- include/nether_DummyBackend.h | 43 ++- include/nether_FileBackend.h | 67 +++-- include/nether_Manager.h | 50 ++-- include/nether_Netlink.h | 62 ++--- include/nether_PolicyBackend.h | 32 ++- include/nether_Types.h | 223 +++++++-------- include/nether_Utils.h | 255 ++++++++--------- nether.cbp | 130 --------- packaging/nether.spec | 14 +- src/CMakeLists.txt | 4 +- src/logger/backend-file.cpp | 25 +- src/logger/backend-journal.cpp | 73 ++--- src/logger/backend-stderr.cpp | 59 ++-- src/logger/backend-syslog.cpp | 63 +++-- src/logger/ccolor.cpp | 17 +- src/logger/formatter.cpp | 190 ++++++------- src/logger/level.cpp | 156 +++++++---- src/logger/logger-scope.cpp | 59 ++-- src/logger/logger.cpp | 70 ++--- src/nether_CynaraBackend.cpp | 205 +++++++------- src/nether_FileBackend.cpp | 141 +++++----- src/nether_Main.cpp | 388 +++++++++++++------------- src/nether_Manager.cpp | 546 +++++++++++++++++++------------------ src/nether_Netlink.cpp | 262 +++++++++--------- src/nether_NetworkUtils.cpp | 186 +++++++------ 39 files changed, 1904 insertions(+), 1938 deletions(-) delete mode 100644 nether.cbp diff --git a/CMakeLists.txt b/CMakeLists.txt index 18fbea1..ff080b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,12 @@ CMAKE_MINIMUM_REQUIRED (VERSION 2.6) PROJECT (nether) INCLUDE (FindPkgConfig) -SET (CMAKE_CXX_FLAGS "-std=c++11") +IF (CMAKE_BUILD_TYPE MATCHES DEBUG) + SET (CMAKE_CXX_FLAGS "-g -Wall -Wextra -std=c++11") +ELSE () + SET (CMAKE_CXX_FLAGS "-O3 -fomit-frame-pointer -std=c++11") +ENDIF (CMAKE_BUILD_TYPE MATCHES DEBUG) + SET (CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) IF (NOT DEFINED SYSCONF_INSTALL_DIR) @@ -27,7 +32,7 @@ IF (NOT DEFINED SYSCONF_INSTALL_DIR) ENDIF (NOT DEFINED SYSCONF_INSTALL_DIR) IF (NOT DEFINED SYSTEMD_UNIT_DIR) - SET(SYSTEMD_UNIT_DIR "${CMAKE_INSTALL_PREFIX}/lib/systemd/system") + SET(SYSTEMD_UNIT_DIR "${CMAKE_INSTALL_PREFIX}/lib/systemd/system") ENDIF (NOT DEFINED SYSTEMD_UNIT_DIR) ADD_SUBDIRECTORY (src) diff --git a/include/logger/backend-file.hpp b/include/logger/backend-file.hpp index 2fc4822..1cf69d3 100644 --- a/include/logger/backend-file.hpp +++ b/include/logger/backend-file.hpp @@ -27,19 +27,21 @@ #include "logger/backend.hpp" -namespace logger { +namespace logger +{ -class FileBackend : public LogBackend { -public: - FileBackend(const std::string &filePath) : mfilePath(filePath) {} - void log(LogLevel logLevel, - const std::string& file, - const unsigned int& line, - const std::string& func, - const std::string& message) override; -private: - std::string mfilePath; -}; + class FileBackend : public LogBackend + { + public: + FileBackend(const std::string &filePath) : mfilePath(filePath) {} + void log(LogLevel logLevel, + const std::string& file, + const unsigned int& line, + const std::string& func, + const std::string& message) override; + private: + std::string mfilePath; + }; } // namespace logger diff --git a/include/logger/backend-journal.hpp b/include/logger/backend-journal.hpp index e566ed1..b4ef77b 100644 --- a/include/logger/backend-journal.hpp +++ b/include/logger/backend-journal.hpp @@ -27,19 +27,21 @@ #include "logger/backend.hpp" -namespace logger { +namespace logger +{ -/** - * systemd journal logging backend - */ -class SystemdJournalBackend : public LogBackend { -public: - void log(LogLevel logLevel, - const std::string& file, - const unsigned int& line, - const std::string& func, - const std::string& message) override; -}; + /** + * systemd journal logging backend + */ + class SystemdJournalBackend : public LogBackend + { + public: + void log(LogLevel logLevel, + const std::string& file, + const unsigned int& line, + const std::string& func, + const std::string& message) override; + }; } // namespace logger diff --git a/include/logger/backend-null.hpp b/include/logger/backend-null.hpp index 4a7e8a9..1ad2e5c 100644 --- a/include/logger/backend-null.hpp +++ b/include/logger/backend-null.hpp @@ -27,19 +27,21 @@ #include "logger/backend.hpp" -namespace logger { +namespace logger +{ -/** - * Null logging backend - */ -class NullLogger : public LogBackend { -public: - void log(LogLevel /*logLevel*/, - const std::string& /*file*/, - const unsigned int& /*line*/, - const std::string& /*func*/, - const std::string& /*message*/) override {} -}; + /** + * Null logging backend + */ + class NullLogger : public LogBackend + { + public: + void log(LogLevel /*logLevel*/, + const std::string& /*file*/, + const unsigned int& /*line*/, + const std::string& /*func*/, + const std::string& /*message*/) override {} + }; } // namespace logger diff --git a/include/logger/backend-stderr.hpp b/include/logger/backend-stderr.hpp index 919e24e..57741ff 100644 --- a/include/logger/backend-stderr.hpp +++ b/include/logger/backend-stderr.hpp @@ -27,22 +27,24 @@ #include "logger/backend.hpp" -namespace logger { +namespace logger +{ -/** - * Stderr logging backend - */ -class StderrBackend : public LogBackend { -public: - StderrBackend(const bool _useColours=true) : useColours(_useColours) {} - void log(LogLevel logLevel, - const std::string& file, - const unsigned int& line, - const std::string& func, - const std::string& message) override; -private: - bool useColours; -}; + /** + * Stderr logging backend + */ + class StderrBackend : public LogBackend + { + public: + StderrBackend(const bool _useColours=true) : useColours(_useColours) {} + void log(LogLevel logLevel, + const std::string& file, + const unsigned int& line, + const std::string& func, + const std::string& message) override; + private: + bool useColours; + }; } // namespace logger diff --git a/include/logger/backend-syslog.hpp b/include/logger/backend-syslog.hpp index 045fdec..f6f709c 100644 --- a/include/logger/backend-syslog.hpp +++ b/include/logger/backend-syslog.hpp @@ -27,16 +27,18 @@ #include "logger/backend.hpp" -namespace logger { +namespace logger +{ -class SyslogBackend : public LogBackend { -public: - void log(LogLevel logLevel, - const std::string& file, - const unsigned int& line, - const std::string& func, - const std::string& message) override; -}; + class SyslogBackend : public LogBackend + { + public: + void log(LogLevel logLevel, + const std::string& file, + const unsigned int& line, + const std::string& func, + const std::string& message) override; + }; } // namespace logger diff --git a/include/logger/backend.hpp b/include/logger/backend.hpp index 99b0c49..381d9b7 100644 --- a/include/logger/backend.hpp +++ b/include/logger/backend.hpp @@ -29,20 +29,22 @@ #include -namespace logger { - -/** - * Abstract class for logger - */ -class LogBackend { -public: - virtual void log(LogLevel logLevel, - const std::string& file, - const unsigned int& line, - const std::string& func, - const std::string& message) = 0; - virtual ~LogBackend() {} -}; +namespace logger +{ + + /** + * Abstract class for logger + */ + class LogBackend + { + public: + virtual void log(LogLevel logLevel, + const std::string& file, + const unsigned int& line, + const std::string& func, + const std::string& message) = 0; + virtual ~LogBackend() {} + }; } // namespace logger diff --git a/include/logger/ccolor.hpp b/include/logger/ccolor.hpp index 47cc25e..c39b8ae 100644 --- a/include/logger/ccolor.hpp +++ b/include/logger/ccolor.hpp @@ -27,26 +27,29 @@ #include -namespace logger { - -enum class Color : unsigned int { - DEFAULT = 0, - BLACK = 90, - RED = 91, - GREEN = 92, - YELLOW = 93, - BLUE = 94, - MAGENTA = 95, - CYAN = 96, - WHITE = 97 -}; - -enum class Attributes : unsigned int { - DEFAULT = 0, - BOLD = 1 -}; - -std::string getConsoleEscapeSequence(Attributes attr, Color color); +namespace logger +{ + + enum class Color : unsigned int + { + DEFAULT = 0, + BLACK = 90, + RED = 91, + GREEN = 92, + YELLOW = 93, + BLUE = 94, + MAGENTA = 95, + CYAN = 96, + WHITE = 97 + }; + + enum class Attributes : unsigned int + { + DEFAULT = 0, + BOLD = 1 + }; + + std::string getConsoleEscapeSequence(Attributes attr, Color color); } // namespace logger diff --git a/include/logger/formatter.hpp b/include/logger/formatter.hpp index 3af0763..09a1c04 100644 --- a/include/logger/formatter.hpp +++ b/include/logger/formatter.hpp @@ -29,21 +29,23 @@ #include -namespace logger { - -class LogFormatter { -public: - static unsigned int getCurrentThread(void); - static std::string getCurrentTime(void); - static std::string getConsoleColor(LogLevel logLevel); - static std::string getDefaultConsoleColor(void); - static std::string stripProjectDir(const std::string& file, - const std::string& rootDir); - static std::string getHeader(LogLevel logLevel, - const std::string& file, - const unsigned int& line, - const std::string& func); -}; +namespace logger +{ + + class LogFormatter + { + public: + static unsigned int getCurrentThread(void); + static std::string getCurrentTime(void); + static std::string getConsoleColor(LogLevel logLevel); + static std::string getDefaultConsoleColor(void); + static std::string stripProjectDir(const std::string& file, + const std::string& rootDir); + static std::string getHeader(LogLevel logLevel, + const std::string& file, + const unsigned int& line, + const std::string& func); + }; } // namespace logger diff --git a/include/logger/level.hpp b/include/logger/level.hpp index 7902301..80e698d 100644 --- a/include/logger/level.hpp +++ b/include/logger/level.hpp @@ -27,28 +27,30 @@ #include -namespace logger { - -enum class LogLevel { - TRACE, - DEBUG, - INFO, - WARN, - ERROR, - HELP -}; - -/** - * @param logLevel LogLevel - * @return std::sting representation of the LogLevel value - */ -std::string toString(const LogLevel logLevel); - -/** - * @param level string representation of log level - * @return parsed LogLevel value - */ -LogLevel parseLogLevel(const std::string& level); +namespace logger +{ + + enum class LogLevel + { + TRACE, + DEBUG, + INFO, + WARN, + ERROR, + HELP + }; + + /** + * @param logLevel LogLevel + * @return std::sting representation of the LogLevel value + */ + std::string toString(const LogLevel logLevel); + + /** + * @param level string representation of log level + * @return parsed LogLevel value + */ + LogLevel parseLogLevel(const std::string& level); } // namespace logger diff --git a/include/logger/logger-scope.hpp b/include/logger/logger-scope.hpp index cefd912..fa4fc04 100644 --- a/include/logger/logger-scope.hpp +++ b/include/logger/logger-scope.hpp @@ -28,45 +28,46 @@ #include #include -namespace logger { - -class SStreamWrapper +namespace logger { -public: - operator std::string() const; - template - SStreamWrapper& operator<<(const T& b) - { - this->mSStream << b; - return *this; - } + class SStreamWrapper + { + public: + operator std::string() const; -private: - std::ostringstream mSStream; -}; + template + SStreamWrapper& operator<<(const T& b) + { + this->mSStream << b; + return *this; + } -/** - * Class specifically for scope debug logging. Should be used at the beggining of a scope. - * Constructor marks scope enterance, destructor marks scope leave. - */ -class LoggerScope -{ -public: - LoggerScope(const std::string& file, - const unsigned int line, - const std::string& func, - const std::string& message, - const std::string& rootDir); - ~LoggerScope(); + private: + std::ostringstream mSStream; + }; + + /** + * Class specifically for scope debug logging. Should be used at the beggining of a scope. + * Constructor marks scope enterance, destructor marks scope leave. + */ + class LoggerScope + { + public: + LoggerScope(const std::string& file, + const unsigned int line, + const std::string& func, + const std::string& message, + const std::string& rootDir); + ~LoggerScope(); -private: - const std::string mFile; - const unsigned int mLine; - const std::string mFunc; - const std::string mMessage; - const std::string mRootDir; -}; + private: + const std::string mFile; + const unsigned int mLine; + const std::string mFunc; + const std::string mMessage; + const std::string mRootDir; + }; } // namespace logger diff --git a/include/logger/logger.hpp b/include/logger/logger.hpp index d596a20..050416e 100644 --- a/include/logger/logger.hpp +++ b/include/logger/logger.hpp @@ -36,24 +36,26 @@ #define PROJECT_SOURCE_DIR "" #endif -namespace logger { +namespace logger +{ -class LogBackend; + class LogBackend; -class Logger { -public: - static void logMessage(LogLevel logLevel, - const std::string& message, - const std::string& file, - const unsigned int line, - const std::string& func, - const std::string& rootDir); + class Logger + { + public: + static void logMessage(LogLevel logLevel, + const std::string& message, + const std::string& file, + const unsigned int line, + const std::string& func, + const std::string& rootDir); - static void setLogLevel(const LogLevel level); - static void setLogLevel(const std::string& level); - static LogLevel getLogLevel(void); - static void setLogBackend(LogBackend* pBackend); -}; + static void setLogLevel(const LogLevel level); + static void setLogLevel(const std::string& level); + static LogLevel getLogLevel(void); + static void setLogBackend(LogBackend* pBackend); + }; } // namespace logger diff --git a/include/nether_CynaraBackend.h b/include/nether_CynaraBackend.h index fc21d68..c7f9fff 100644 --- a/include/nether_CynaraBackend.h +++ b/include/nether_CynaraBackend.h @@ -35,39 +35,38 @@ static const std::string cynaraErrorCodeToString(int cynaraErrorCode) { - char errorString[512]; - int ret; + char errorString[512]; + int ret; - if ((ret = cynara_strerror(cynaraErrorCode, errorString, 512)) == CYNARA_API_SUCCESS) - return (std::string(errorString, strlen(errorString))); - else - return ("Failed to get error string representation, code="+ret); + if((ret = cynara_strerror(cynaraErrorCode, errorString, 512)) == CYNARA_API_SUCCESS) + return (std::string(errorString, strlen(errorString))); + else + return ("Failed to get error string representation, code="+ret); } class NetherManager; class NetherCynaraBackend : public NetherPolicyBackend { - public: - NetherCynaraBackend(const NetherConfig &netherConfig); - ~NetherCynaraBackend(); - const bool initialize(); - const bool isValid(); - const bool enqueueVerdict (const NetherPacket &packet); - const bool processEvents(); - const int getDescriptor(); - const NetherDescriptorStatus getDescriptorStatus(); - void setCynaraDescriptor(const int _currentCynaraDescriptor, const NetherDescriptorStatus _currentCynaraDescriptorStatus); - void setCynaraVerdict(cynara_check_id checkId, int cynaraResult); - static void statusCallback(int oldFd, int newFd, cynara_async_status status, void *data); - static void checkCallback(cynara_check_id check_id, cynara_async_call_cause cause, int response, void *data); + public: + NetherCynaraBackend(const NetherConfig &netherConfig); + ~NetherCynaraBackend(); + bool initialize(); + bool enqueueVerdict(const NetherPacket &packet); + bool processEvents(); + int getDescriptor(); + NetherDescriptorStatus getDescriptorStatus(); + void setCynaraDescriptor(const int _currentCynaraDescriptor, const NetherDescriptorStatus _currentCynaraDescriptorStatus); + void setCynaraVerdict(cynara_check_id checkId, int cynaraResult); + static void statusCallback(int oldFd, int newFd, cynara_async_status status, void *data); + static void checkCallback(cynara_check_id check_id, cynara_async_call_cause cause, int response, void *data); - private: - cynara_async *cynaraContext; - NetherDescriptorStatus currentCynaraDescriptorStatus; - int currentCynaraDescriptor; - std::vector responseQueue; - int cynaraLastResult; + private: + cynara_async *cynaraContext; + NetherDescriptorStatus currentCynaraDescriptorStatus; + int currentCynaraDescriptor; + std::vector responseQueue; + int cynaraLastResult; }; #endif // HAVE_CYNARA diff --git a/include/nether_Daemon.h b/include/nether_Daemon.h index 03a9c79..760fadf 100644 --- a/include/nether_Daemon.h +++ b/include/nether_Daemon.h @@ -35,56 +35,58 @@ bool runAsDaemon() { - pid_t pid = fork(); + pid_t pid = fork(); - if (pid == -1) - return (false); - else if (pid != 0) - exit (0); + if(pid == -1) + return (false); + else + if(pid != 0) + exit(0); - if (setsid() == -1) - return (false); + if(setsid() == -1) + return (false); - /* Catch, ignore and handle signals */ - signal(SIGCHLD, SIG_IGN); - signal(SIGHUP, SIG_IGN); + /* Catch, ignore and handle signals */ + signal(SIGCHLD, SIG_IGN); + signal(SIGHUP, SIG_IGN); - pid = fork(); + pid = fork(); - /* - * Fork a second child and exit immediately to prevent zombies. This - * causes the second child process to be orphaned, making the init - * process responsible for its cleanup. And, since the first child is - * a session leader without a controlling terminal, it's possible for - * it to acquire one by opening a terminal in the future (System V- - * based systems). This second fork guarantees that the child is no - * longer a session leader, preventing the daemon from ever acquiring - * a controlling terminal. - */ - if (pid == -1) - return (false); - else if (pid != 0) - exit(0); + /* + * Fork a second child and exit immediately to prevent zombies. This + * causes the second child process to be orphaned, making the init + * process responsible for its cleanup. And, since the first child is + * a session leader without a controlling terminal, it's possible for + * it to acquire one by opening a terminal in the future (System V- + * based systems). This second fork guarantees that the child is no + * longer a session leader, preventing the daemon from ever acquiring + * a controlling terminal. + */ + if(pid == -1) + return (false); + else + if(pid != 0) + exit(0); - if (chdir("/") == -1) - return (false); + if(chdir("/") == -1) + return (false); - umask(0); + umask(0); - /** Close all open file descriptors */ - for (int x = sysconf(_SC_OPEN_MAX); x>0; x--) - { - close (x); - } + /** Close all open file descriptors */ + for(int x = sysconf(_SC_OPEN_MAX); x>0; x--) + { + close(x); + } - if (open("/dev/null",O_RDONLY) == -1) - return (false); + if(open("/dev/null",O_RDONLY) == -1) + return (false); - if (open("/dev/null",O_WRONLY) == -1) - return (false); + if(open("/dev/null",O_WRONLY) == -1) + return (false); - if (open("/dev/null",O_RDWR) == -1) - return (false); + if(open("/dev/null",O_RDWR) == -1) + return (false); - return (true); + return (true); } diff --git a/include/nether_DummyBackend.h b/include/nether_DummyBackend.h index 8bbee85..c5316eb 100644 --- a/include/nether_DummyBackend.h +++ b/include/nether_DummyBackend.h @@ -29,30 +29,25 @@ class NetherDummyBackend : public NetherPolicyBackend { - public: - NetherDummyBackend(const NetherConfig &netherConfig) - : NetherPolicyBackend(netherConfig) {} - ~NetherDummyBackend() {} - - const bool isValid() - { - return (true); - } - - const bool initialize() - { - return (true); - } - - const bool enqueueVerdict(const NetherPacket &packet) - { - return (castVerdict (packet, netherConfig.defaultVerdict)); - } - - const bool processEvents() - { - return (true); - } + public: + NetherDummyBackend(const NetherConfig &netherConfig) + : NetherPolicyBackend(netherConfig) {} + ~NetherDummyBackend() {} + + bool initialize() + { + return (true); + } + + bool enqueueVerdict(const NetherPacket &packet) + { + return (castVerdict(packet, netherConfig.defaultVerdict)); + } + + bool processEvents() + { + return (true); + } }; #endif diff --git a/include/nether_FileBackend.h b/include/nether_FileBackend.h index c3cd544..63c8a77 100644 --- a/include/nether_FileBackend.h +++ b/include/nether_FileBackend.h @@ -39,49 +39,56 @@ class NetherManager; enum PolicyFileTokens { - uidT, - gidT, - secctxT, - verdictT + uidToken, + gidToken, + secctxToken, + verdictToken }; struct PolicyEntry { - uid_t uid; - gid_t gid; - std::string securityContext; - NetherVerdict verdict; + uid_t uid; + gid_t gid; + std::string securityContext; + NetherVerdict verdict; }; static const std::string dumpPolicyEntry(const PolicyEntry &entry) { - std::stringstream stream; - stream << "UID="; - if (entry.uid == NETHER_INVALID_UID) stream << "*"; else stream << entry.uid; - stream << " GID="; - if (entry.gid == NETHER_INVALID_GID) stream << "*"; else stream << entry.gid; - stream << " SECCTX="; - if (entry.securityContext.empty()) stream << "*"; else stream << entry.securityContext; - stream << " VERDICT="; - stream << verdictToString(entry.verdict); + std::stringstream stream; + stream << "UID="; + if(entry.uid == NETHER_INVALID_UID) + stream << "*"; + else + stream << entry.uid; + stream << " GID="; + if(entry.gid == NETHER_INVALID_GID) + stream << "*"; + else stream << entry.gid; + stream << " SECCTX="; + if(entry.securityContext.empty()) + stream << "*"; + else + stream << entry.securityContext; + stream << " VERDICT="; + stream << verdictToString(entry.verdict); - return (stream.str()); + return (stream.str()); } class NetherFileBackend : public NetherPolicyBackend { - public: - NetherFileBackend(const NetherConfig &netherConfig); - ~NetherFileBackend(); - const bool isValid(); - const bool initialize(); - const bool reload(); - const bool enqueueVerdict(const NetherPacket &packet); - const bool parsePolicyFile(std::ifstream &policyFile); - const bool processEvents() { return (true); } - std::vector split(const std::string &str, const std::string &delim); - private: - std::vector policy; + public: + NetherFileBackend(const NetherConfig &netherConfig); + ~NetherFileBackend(); + bool initialize(); + bool reload(); + bool enqueueVerdict(const NetherPacket &packet); + bool parsePolicyFile(std::ifstream &policyFile); + bool processEvents() { return (true); } + std::vector split(const std::string &str, const std::string &delim); + private: + std::vector policy; }; #endif diff --git a/include/nether_Manager.h b/include/nether_Manager.h index 5407a63..5865fcf 100644 --- a/include/nether_Manager.h +++ b/include/nether_Manager.h @@ -32,34 +32,34 @@ class NetherManager : public NetherVerdictListener, public NetherProcessedPacketListener { - public: - NetherManager(const NetherConfig &_netherConfig); - ~NetherManager(); - const bool initialize(); - const bool process(); - NetherConfig &getConfig(); - static NetherPolicyBackend *getPolicyBackend(const NetherConfig &netherConfig, const bool primary = true); - bool verdictCast (const u_int32_t packetId, const NetherVerdict verdict); - void packetReceived (const NetherPacket &packet); - const bool restoreRules(); + public: + NetherManager(const NetherConfig &_netherConfig); + ~NetherManager(); + bool initialize(); + bool process(); + NetherConfig &getConfig(); + static NetherPolicyBackend *getPolicyBackend(const NetherConfig &netherConfig, const bool primary = true); + bool verdictCast(const u_int32_t packetId, const NetherVerdict verdict); + void packetReceived(const NetherPacket &packet); + bool restoreRules(); - private: - static const bool isCommandAvailable(const std::string &command); - void handleSignal(); - const bool handleNetlinkpacket(); - void setupSelectSockets(fd_set &watchedReadDescriptorsSet, fd_set &watchedWriteDescriptorsSet, struct timeval &timeoutSpecification); - std::unique_ptr netherPrimaryPolicyBackend; - std::unique_ptr netherBackupPolicyBackend; - std::unique_ptr netherFallbackPolicyBackend; - std::unique_ptr netherNetlink; - NetherConfig netherConfig; - int netlinkDescriptor; - int backendDescriptor; - int signalDescriptor; + private: + static bool isCommandAvailable(const std::string &command); + void handleSignal(); + bool handleNetlinkpacket(); + void setupSelectSockets(fd_set &watchedReadDescriptorsSet, fd_set &watchedWriteDescriptorsSet, struct timeval &timeoutSpecification); + std::unique_ptr netherPrimaryPolicyBackend; + std::unique_ptr netherBackupPolicyBackend; + std::unique_ptr netherFallbackPolicyBackend; + std::unique_ptr netherNetlink; + NetherConfig netherConfig; + int netlinkDescriptor; + int backendDescriptor; + int signalDescriptor; #ifdef HAVE_AUDIT - int auditDescriptor; + int auditDescriptor; #endif // HAVE_AUDIT - sigset_t signalMask; + sigset_t signalMask; }; #endif diff --git a/include/nether_Netlink.h b/include/nether_Netlink.h index df852e9..39a1b44 100644 --- a/include/nether_Netlink.h +++ b/include/nether_Netlink.h @@ -22,36 +22,34 @@ * @brief netlink handler class for nether */ -#ifndef NETHER_NETLINK_H -#define NETHER_NETLINK_H - -#include "nether_Types.h" +#ifndef NETHER_NETLINK_H +#define NETHER_NETLINK_H + +#include "nether_Types.h" #include "nether_Utils.h" - -class NetherManager; - -class NetherNetlink : public NetherPacketProcessor -{ - public: - NetherNetlink(NetherConfig &netherConfig); - ~NetherNetlink(); - const bool initialize(); - const bool reload(); - static int callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data); - const bool processPacket (char *packetBuffer, const int packetReadSize); - void setVerdict(const u_int32_t packetId, const NetherVerdict verdict); - int getDescriptor(); - const bool isValid(); - - protected: - NetherPacket *processedPacket; - - private: - struct nfq_q_handle *queueHandle; - struct nfq_handle *nfqHandle; - struct nlif_handle *nlif; - int fd; - uint32_t queue; -}; - -#endif // NETLINK_H_INCLUDED + +class NetherManager; + +class NetherNetlink : public NetherPacketProcessor +{ + public: + NetherNetlink(NetherConfig &netherConfig); + ~NetherNetlink(); + bool initialize(); + bool reload(); + static int callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data); + bool processPacket(char *packetBuffer, const int packetReadSize); + void setVerdict(const u_int32_t packetId, const NetherVerdict verdict); + int getDescriptor(); + + protected: + NetherPacket *processedPacket; + + private: + struct nfq_q_handle *queueHandle; + struct nfq_handle *nfqHandle; + struct nlif_handle *nlif; + uint32_t queue; +}; + +#endif // NETLINK_H_INCLUDED diff --git a/include/nether_PolicyBackend.h b/include/nether_PolicyBackend.h index 4d2145f..c17bfe4 100644 --- a/include/nether_PolicyBackend.h +++ b/include/nether_PolicyBackend.h @@ -30,19 +30,27 @@ class NetherPolicyBackend : public NetherVerdictCaster { - public: - NetherPolicyBackend(const NetherConfig &_netherConfig) : netherConfig(_netherConfig) {} - virtual ~NetherPolicyBackend() {} - virtual const bool enqueueVerdict (const NetherPacket &packet) = 0; - virtual const bool initialize() = 0; - virtual const bool reload() { return (true); }; - virtual const bool isValid() = 0; - virtual const int getDescriptor() { return (-1); } - virtual const NetherDescriptorStatus getDescriptorStatus() { return (NetherDescriptorStatus::unknownStatus); } - virtual const bool processEvents() = 0; + public: + NetherPolicyBackend(const NetherConfig &_netherConfig) : netherConfig(_netherConfig) {} + virtual ~NetherPolicyBackend() {} + virtual bool enqueueVerdict(const NetherPacket &packet) = 0; + virtual bool initialize() = 0; + virtual bool reload() + { + return (true); + }; + virtual int getDescriptor() + { + return (-1); + } + virtual NetherDescriptorStatus getDescriptorStatus() + { + return (NetherDescriptorStatus::unknownStatus); + } + virtual bool processEvents() = 0; - protected: - NetherConfig netherConfig; + protected: + NetherConfig netherConfig; }; #endif diff --git a/include/nether_Types.h b/include/nether_Types.h index 8802b47..9991a30 100644 --- a/include/nether_Types.h +++ b/include/nether_Types.h @@ -44,12 +44,14 @@ #include #include #include +#include +#include #include #include #include #if defined(HAVE_AUDIT) - #include +#include #endif // HAVE_AUDIT #include @@ -59,15 +61,15 @@ #include "logger/backend-syslog.hpp" #if defined(HAVE_SYSTEMD_JOURNAL) - #include "logger/backend-journal.hpp" +#include "logger/backend-journal.hpp" #endif // HAVE_SYSTEMD_JOURNAL #if defined(HAVE_CYNARA) - #define NETHER_PRIMARY_BACKEND NetherPolicyBackendType::cynaraBackend - #define NETHER_BACKUP_BACKEND NetherPolicyBackendType::fileBackend +#define NETHER_PRIMARY_BACKEND NetherPolicyBackendType::cynaraBackend +#define NETHER_BACKUP_BACKEND NetherPolicyBackendType::fileBackend #else - #define NETHER_PRIMARY_BACKEND fileBackend - #define NETHER_BACKUP_BACKEND dummyBackend +#define NETHER_PRIMARY_BACKEND fileBackend +#define NETHER_BACKUP_BACKEND dummyBackend #endif // HAVE_CYNARA #define NETHER_DEFAULT_VERDICT NetherVerdict::allowAndLog @@ -83,159 +85,164 @@ #define NETHER_LOG_BACKEND NetherLogBackendType::stderrBackend #define NETHER_IPTABLES_RESTORE_PATH "/usr/sbin/iptables-restore" #ifndef NETHER_RULES_PATH - #define NETHER_RULES_PATH "/etc/nether/nether.rules" +#define NETHER_RULES_PATH "/etc/nether/nether.rules" #endif // NETHER_RULES_PATH #ifndef NETHER_POLICY_FILE - #define NETHER_POLICY_FILE "/etc/nether/nether.policy" +#define NETHER_POLICY_FILE "/etc/nether/nether.policy" #endif // NETHER_POLICY_FILE enum class NetherPolicyBackendType : std::uint8_t { - cynaraBackend, - fileBackend, - dummyBackend + cynaraBackend, + fileBackend, + dummyBackend }; enum class NetherLogBackendType : std::uint8_t { - stderrBackend, - syslogBackend, - journalBackend, - logfileBackend, - nullBackend + stderrBackend, + syslogBackend, + journalBackend, + logfileBackend, + nullBackend }; enum class NetherVerdict : std::uint8_t { - allow, - allowAndLog, - deny, - noVerdictYet + allow, + allowAndLog, + deny, + noVerdictYet }; enum class NetherDescriptorStatus : std::uint8_t { - readOnly, - writeOnly, - readWrite, - unknownStatus + readOnly, + writeOnly, + readWrite, + unknownStatus }; enum class NetherTransportType : std::uint8_t { - TCP, - UDP, - ICMP, - IGMP, - unknownTransportType + TCP, + UDP, + ICMP, + IGMP, + unknownTransportType }; enum class NetherProtocolType : std::uint8_t { - IPv4, - IPv6, - unknownProtocolType + IPv4, + IPv6, + unknownProtocolType }; struct NetherPacket { - u_int32_t id; - std::string securityContext; - uid_t uid; - gid_t gid; - pid_t pid; - NetherTransportType transportType; - NetherProtocolType protocolType; - char localAddress[NETHER_NETWORK_ADDR_LEN]; - int localPort; - char remoteAddress[NETHER_NETWORK_ADDR_LEN]; - int remotePort; + uid_t uid; + u_int32_t id; + std::string securityContext; + int remotePort; + int localPort; + gid_t gid; + pid_t pid; + char localAddress[NETHER_NETWORK_ADDR_LEN]; + char remoteAddress[NETHER_NETWORK_ADDR_LEN]; + NetherTransportType transportType; + NetherProtocolType protocolType; }; struct NetherConfig { - NetherVerdict defaultVerdict = NETHER_DEFAULT_VERDICT; - NetherPolicyBackendType primaryBackendType = NETHER_PRIMARY_BACKEND; - NetherPolicyBackendType backupBackendType = NETHER_BACKUP_BACKEND; - NetherLogBackendType logBackend = NETHER_LOG_BACKEND; - int primaryBackendRetries = 3; - int backupBackendRetries = 3; - int debugMode = 0; - int daemonMode = 0; - int queueNumber = 0; - std::string backupBackendArgs = NETHER_POLICY_FILE; - std::string primaryBackendArgs; - std::string logBackendArgs; - std::string rulesPath = NETHER_RULES_PATH; - std::string iptablesRestorePath = NETHER_IPTABLES_RESTORE_PATH; - uint8_t markDeny = NETLINK_DROP_MARK; - uint8_t markAllowAndLog = NETLINK_ALLOWLOG_MARK; - int enableAudit = 0; - int noRules = 0; + NetherVerdict defaultVerdict = NETHER_DEFAULT_VERDICT; + NetherPolicyBackendType primaryBackendType = NETHER_PRIMARY_BACKEND; + NetherPolicyBackendType backupBackendType = NETHER_BACKUP_BACKEND; + NetherLogBackendType logBackend = NETHER_LOG_BACKEND; + uint8_t markDeny = NETLINK_DROP_MARK; + uint8_t markAllowAndLog = NETLINK_ALLOWLOG_MARK; + int primaryBackendRetries = 3; + int backupBackendRetries = 3; + int debugMode = 0; + int daemonMode = 0; + int queueNumber = 0; + int enableAudit = 0; + int noRules = 0; + std::string backupBackendArgs = NETHER_POLICY_FILE; + std::string primaryBackendArgs; + std::string logBackendArgs; + std::string rulesPath = NETHER_RULES_PATH; + std::string iptablesRestorePath = NETHER_IPTABLES_RESTORE_PATH; }; class NetherVerdictListener { - public: - virtual bool verdictCast (const u_int32_t packetId, const NetherVerdict verdict) = 0; + public: + virtual bool verdictCast(const u_int32_t packetId, const NetherVerdict verdict) = 0; }; class NetherVerdictCaster { - public: - NetherVerdictCaster() : verdictListener(nullptr) {} - virtual ~NetherVerdictCaster() {} - - void setListener(NetherVerdictListener *listenerToSet) - { - verdictListener = listenerToSet; - } - - bool castVerdict (const NetherPacket &packet, const NetherVerdict verdict) - { - if (verdictListener) - return (verdictListener->verdictCast(packet.id, verdict)); - return (false); - } - - bool castVerdict (const u_int32_t packetId, const NetherVerdict verdict) - { - if (verdictListener) - return (verdictListener->verdictCast(packetId, verdict)); - return (false); - } - - protected: - NetherVerdictListener *verdictListener; + public: + NetherVerdictCaster() : verdictListener(nullptr) {} + virtual ~NetherVerdictCaster() {} + + void setListener(NetherVerdictListener *listenerToSet) + { + verdictListener = listenerToSet; + } + + bool castVerdict(const NetherPacket &packet, const NetherVerdict verdict) + { + if(verdictListener) + return (verdictListener->verdictCast(packet.id, verdict)); + return (false); + } + + bool castVerdict(const u_int32_t packetId, const NetherVerdict verdict) + { + if(verdictListener) + return (verdictListener->verdictCast(packetId, verdict)); + return (false); + } + + protected: + NetherVerdictListener *verdictListener; }; class NetherProcessedPacketListener { - public: - virtual void packetReceived (const NetherPacket &packet) = 0; + public: + virtual void packetReceived(const NetherPacket &packet) = 0; }; class NetherPacketProcessor { - public: - NetherPacketProcessor(NetherConfig &_netherConfig) : netherConfig(_netherConfig), packetListener(nullptr) {} - virtual ~NetherPacketProcessor() {} - virtual const bool reload() { return (true); } - void setListener(NetherProcessedPacketListener *listenerToSet) - { - packetListener = listenerToSet; - } - - void processNetherPacket (NetherPacket packetInfoToWrite) - { - if (packetListener) packetListener->packetReceived(packetInfoToWrite); - } - - virtual void setVerdict(const NetherPacket &packet, const NetherVerdict verdict) {} - protected: - NetherProcessedPacketListener *packetListener; - NetherConfig netherConfig; + public: + NetherPacketProcessor(NetherConfig &_netherConfig) + : packetListener(nullptr), netherConfig(_netherConfig) {} + virtual ~NetherPacketProcessor() {} + virtual bool reload() + { + return (true); + } + void setListener(NetherProcessedPacketListener *listenerToSet) + { + packetListener = listenerToSet; + } + + void processNetherPacket(NetherPacket packetInfoToWrite) + { + if(packetListener) packetListener->packetReceived(packetInfoToWrite); + } + + virtual void setVerdict(const u_int32_t packetId, const NetherVerdict verdict) = 0; + + protected: + NetherProcessedPacketListener *packetListener; + NetherConfig netherConfig; }; #endif diff --git a/include/nether_Utils.h b/include/nether_Utils.h index 7298a5c..764ce78 100644 --- a/include/nether_Utils.h +++ b/include/nether_Utils.h @@ -22,168 +22,171 @@ * @brief utility functions */ - #ifndef NETHER_UTILS_H #define NETHER_UTILS_H + #include "nether_Types.h" void decodePacket(NetherPacket &packet, unsigned char *payload); void decodeIPv4Packet(NetherPacket &packet, unsigned char *payload); void decodeIPv6Packet(NetherPacket &packet, unsigned char *payload); void decodeTcp(NetherPacket &packet, unsigned char *payload); void decodeUdp(NetherPacket &packet, unsigned char *payload); -const std::string ipAddressToString(const char *src, enum NetherProtocolType type); +std::string ipAddressToString(const char *src, enum NetherProtocolType type); -template -inline void deleteAndZero (Type& pointer) { delete pointer; pointer = nullptr; } - -static const NetherVerdict stringToVerdict (char *verdictAsString) +static NetherVerdict stringToVerdict(char *verdictAsString) { - if (verdictAsString) - { - if (strncasecmp (verdictAsString, "allow_log", 9) == 0) - return (NetherVerdict::allowAndLog); - if (strncasecmp (verdictAsString, "allow", 6) == 0) - return (NetherVerdict::allow); - if (strncasecmp (verdictAsString, "deny", 4) == 0) - return (NetherVerdict::deny); - } - return (NetherVerdict::allowAndLog); + if(verdictAsString) + { + if(strncasecmp(verdictAsString, "allow_log", 9) == 0) + return (NetherVerdict::allowAndLog); + if(strncasecmp(verdictAsString, "allow", 6) == 0) + return (NetherVerdict::allow); + if(strncasecmp(verdictAsString, "deny", 4) == 0) + return (NetherVerdict::deny); + } + return (NetherVerdict::allowAndLog); } -static const NetherPolicyBackendType stringToBackendType (char *backendAsString) +static NetherPolicyBackendType stringToBackendType(char *backendAsString) { - if (strcasecmp (backendAsString, "cynara") == 0) - return (NetherPolicyBackendType::cynaraBackend); - if (strcasecmp (backendAsString, "file") == 0) - return (NetherPolicyBackendType::fileBackend); - if (strcasecmp (backendAsString, "dummy") == 0) - return (NetherPolicyBackendType::dummyBackend); - - return (NetherPolicyBackendType::dummyBackend); + if(strcasecmp(backendAsString, "cynara") == 0) + return (NetherPolicyBackendType::cynaraBackend); + if(strcasecmp(backendAsString, "file") == 0) + return (NetherPolicyBackendType::fileBackend); + if(strcasecmp(backendAsString, "dummy") == 0) + return (NetherPolicyBackendType::dummyBackend); + + return (NetherPolicyBackendType::dummyBackend); } -static const NetherLogBackendType stringToLogBackendType(char *backendAsString) +static NetherLogBackendType stringToLogBackendType(char *backendAsString) { - if (strcasecmp (backendAsString, "stderr") == 0) - return (NetherLogBackendType::stderrBackend); - if (strcasecmp (backendAsString, "syslog") == 0) - return (NetherLogBackendType::syslogBackend); - if (strcasecmp (backendAsString, "journal") == 0) - return (NetherLogBackendType::journalBackend); - if (strcasecmp (backendAsString, "file") == 0) - return (NetherLogBackendType::logfileBackend); - if (strcasecmp (backendAsString, "null") == 0) - return (NetherLogBackendType::nullBackend); - - return (NetherLogBackendType::nullBackend); + if(strcasecmp(backendAsString, "stderr") == 0) + return (NetherLogBackendType::stderrBackend); + if(strcasecmp(backendAsString, "syslog") == 0) + return (NetherLogBackendType::syslogBackend); + if(strcasecmp(backendAsString, "journal") == 0) + return (NetherLogBackendType::journalBackend); + if(strcasecmp(backendAsString, "file") == 0) + return (NetherLogBackendType::logfileBackend); + if(strcasecmp(backendAsString, "null") == 0) + return (NetherLogBackendType::nullBackend); + + return (NetherLogBackendType::nullBackend); } -static const std::string logBackendTypeToString(const NetherLogBackendType backendType) +static std::string logBackendTypeToString(const NetherLogBackendType backendType) { - switch (backendType) - { - case NetherLogBackendType::stderrBackend: - return ("stderr"); - case NetherLogBackendType::syslogBackend: - return ("syslog"); - case NetherLogBackendType::journalBackend: - return ("journal"); - case NetherLogBackendType::logfileBackend: - return ("file"); - case NetherLogBackendType::nullBackend: - return ("null"); - } - return ("null"); + switch(backendType) + { + case NetherLogBackendType::stderrBackend: + return ("stderr"); + case NetherLogBackendType::syslogBackend: + return ("syslog"); + case NetherLogBackendType::journalBackend: + return ("journal"); + case NetherLogBackendType::logfileBackend: + return ("file"); + case NetherLogBackendType::nullBackend: + return ("null"); + } + return ("null"); } -static const std::string backendTypeToString (const NetherPolicyBackendType backendType) +static std::string backendTypeToString(const NetherPolicyBackendType backendType) { - switch (backendType) - { - case NetherPolicyBackendType::cynaraBackend: - return ("cynara"); - case NetherPolicyBackendType::fileBackend: - return ("file"); - case NetherPolicyBackendType::dummyBackend: - default: - return ("dummy"); - } + switch(backendType) + { + case NetherPolicyBackendType::cynaraBackend: + return ("cynara"); + case NetherPolicyBackendType::fileBackend: + return ("file"); + case NetherPolicyBackendType::dummyBackend: + default: + return ("dummy"); + } } -static const std::string verdictToString (const NetherVerdict verdict) +static std::string verdictToString(const NetherVerdict verdict) { - switch (verdict) - { - case NetherVerdict::allow: - return ("ALLOW"); - case NetherVerdict::allowAndLog: - return ("ALLOW_LOG"); - case NetherVerdict::deny: - return ("DENY"); - } + switch(verdict) + { + case NetherVerdict::allow: + return ("ALLOW"); + case NetherVerdict::allowAndLog: + return ("ALLOW_LOG"); + case NetherVerdict::deny: + return ("DENY"); + case NetherVerdict::noVerdictYet: + return ("NO_VERDICT_YET"); + } + return ("NO_VERDICT_YET"); } -static const std::string transportToString(const NetherTransportType transportType) +static std::string transportToString(const NetherTransportType transportType) { - switch (transportType) - { - case NetherTransportType::TCP: - return ("TCP"); - case NetherTransportType::UDP: - return ("UDP"); - case NetherTransportType::ICMP: - return ("ICMP"); - case NetherTransportType::IGMP: - return ("IGMP"); - case NetherTransportType::unknownTransportType: - default: - return ("UNKNOWN"); - } + switch(transportType) + { + case NetherTransportType::TCP: + return ("TCP"); + case NetherTransportType::UDP: + return ("UDP"); + case NetherTransportType::ICMP: + return ("ICMP"); + case NetherTransportType::IGMP: + return ("IGMP"); + case NetherTransportType::unknownTransportType: + default: + return ("UNKNOWN"); + } } -static const std::string protocolToString(const NetherProtocolType protocolType) +static std::string protocolToString(const NetherProtocolType protocolType) { - switch (protocolType) - { - case NetherProtocolType::IPv4: - return ("IPv4"); - case NetherProtocolType::IPv6: - return ("IPv6"); - default: - return ("UNKNOWN"); - } + switch(protocolType) + { + case NetherProtocolType::IPv4: + return ("IPv4"); + case NetherProtocolType::IPv6: + return ("IPv6"); + default: + return ("UNKNOWN"); + } } -static const std::string packetToString (const NetherPacket &packet) +static std::string packetToString(const NetherPacket &packet) { - std::stringstream stream; - stream << "ID="; - stream << packet.id; - stream << " SECCTX="; - stream << packet.securityContext; - stream << " UID="; - stream << packet.uid; - stream << " PROTO="; - stream << protocolToString(packet.protocolType); - stream << " TRANSPORT="; - stream << transportToString(packet.transportType); - stream << " SADDR="; - stream << ipAddressToString(&packet.localAddress[0], packet.protocolType); - stream << ":"; - stream << packet.localPort; - stream << " DADDR="; - stream << ipAddressToString(&packet.remoteAddress[0], packet.protocolType); - stream << ":"; - stream << packet.remotePort; - return (stream.str()); + std::stringstream stream; + stream << "ID="; + stream << packet.id; + stream << " SECCTX="; + stream << packet.securityContext; + stream << " UID="; + stream << packet.uid; + stream << " GID="; + stream << packet.gid; + stream << " PROTO="; + stream << protocolToString(packet.protocolType); + stream << " TRANSPORT="; + stream << transportToString(packet.transportType); + stream << " SADDR="; + stream << ipAddressToString(&packet.localAddress[0], packet.protocolType); + stream << ":"; + stream << packet.localPort; + stream << " DADDR="; + stream << ipAddressToString(&packet.remoteAddress[0], packet.protocolType); + stream << ":"; + stream << packet.remotePort; + return (stream.str()); } template -std::string stringFormat( const char* format, Args ... args ) +std::string stringFormat(const char* format, Args ... args) { - size_t size = snprintf( nullptr, 0, format, args ... ) + 1; // Extra space for '\0' - std::unique_ptr buf( new char[ size ] ); - snprintf( buf.get(), size, format, args ... ); - return std::string( buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside + size_t size = snprintf(nullptr, 0, format, args ...) + 1; // Extra space for '\0' + std::unique_ptr buf(new char[ size ]); + snprintf(buf.get(), size, format, args ...); + return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside } -#endif + +#endif // NETHER_UTILS_H diff --git a/nether.cbp b/nether.cbp deleted file mode 100644 index 1a6a84e..0000000 --- a/nether.cbp +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - diff --git a/packaging/nether.spec b/packaging/nether.spec index e491b08..1321e58 100644 --- a/packaging/nether.spec +++ b/packaging/nether.spec @@ -1,5 +1,4 @@ Name: nether -Epoch: 1 Version: 0.0.1 Release: 0 Source0: %{name}-%{version}.tar.gz @@ -7,7 +6,6 @@ License: Apache-2.0 Group: Security/Other Summary: Daemon for enforcing network privileges BuildRequires: cmake -BuildRequires: pkgconfig(glib-2.0) BuildRequires: libnetfilter_queue-devel BuildRequires: pkgconfig(cynara-client-async) Requires: iptables @@ -17,7 +15,7 @@ This is a network privilege enforcing service. %files %defattr(644,root,root,755) -%attr(755,root,root) %{_bindir}/nether +%caps(cap_sys_admin,cap_mac_override=ei) %attr(755,root,root) %{_bindir}/nether %dir %{_sysconfdir}/nether %config %{_sysconfdir}/nether/nether.policy %config %{_sysconfdir}/nether/nether.rules @@ -40,7 +38,7 @@ This is a network privilege enforcing service. -DBIN_INSTALL_DIR=%{_bindir} \ -DSYSCONF_INSTALL_DIR=%{_sysconfdir} -make -k %{?jobs:-j%jobs} +make %{?_smp_mflags} %install %make_install @@ -50,11 +48,13 @@ rm -rf %{buildroot} %post # Refresh systemd services list after installation +systemctl daemon-reload || : if [ $1 == 1 ]; then - systemctl daemon-reload || : + systemctl start nether.service || : +fi +if [ $1 == 2 ]; then + systemct restart nether.service || : fi -# set needed caps on the binary to allow restart without loosing them -setcap CAP_SYS_ADMIN,CAP_MAC_OVERRIDE+ei %{_bindir}/nether %preun # Stop the service before uninstall diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 94d5e68..54cc564 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -67,14 +67,14 @@ INCLUDE_DIRECTORIES(../include ${SYSTEMD_INCLUDE_DIRS} ) -TARGET_LINK_LIBRARIES (nether +TARGET_LINK_LIBRARIES (nether ${CYNARA_LIBRARIES} ${NETFILTER_LIBRARIES} ${SYSTEMD_LIBRARIES} ) ADD_DEFINITIONS (-DNETHER_RULES_PATH="${CMAKE_INSTALL_DIR}/etc/nether/nether.rules" - -DNETHER_POLICY_FILE="${CMAKE_INSTALL_DIR}/etc/nether/nether.rules" + -DNETHER_POLICY_FILE="${CMAKE_INSTALL_DIR}/etc/nether/nether.rules" ) INSTALL (TARGETS nether RUNTIME DESTINATION bin) diff --git a/src/logger/backend-file.cpp b/src/logger/backend-file.cpp index f5828e8..15877b5 100644 --- a/src/logger/backend-file.cpp +++ b/src/logger/backend-file.cpp @@ -28,19 +28,20 @@ #include -namespace logger { - -void FileBackend::log(LogLevel logLevel, - const std::string& file, - const unsigned int& line, - const std::string& func, - const std::string& message) +namespace logger { - std::ofstream out(mfilePath, std::ios::app); - out << LogFormatter::getHeader(logLevel, file, line, func); - out << message; - out << std::endl; -} + + void FileBackend::log(LogLevel logLevel, + const std::string& file, + const unsigned int& line, + const std::string& func, + const std::string& message) + { + std::ofstream out(mfilePath, std::ios::app); + out << LogFormatter::getHeader(logLevel, file, line, func); + out << message; + out << std::endl; + } } // namespace logger diff --git a/src/logger/backend-journal.cpp b/src/logger/backend-journal.cpp index af147cd..7144fba 100644 --- a/src/logger/backend-journal.cpp +++ b/src/logger/backend-journal.cpp @@ -28,45 +28,48 @@ #define SD_JOURNAL_SUPPRESS_LOCATION #include -namespace logger { +namespace logger +{ -namespace { + namespace + { -inline int toJournalPriority(LogLevel logLevel) -{ - switch (logLevel) { - case LogLevel::ERROR: - return LOG_ERR; // 3 - case LogLevel::WARN: - return LOG_WARNING; // 4 - case LogLevel::INFO: - return LOG_INFO; // 6 - case LogLevel::DEBUG: - return LOG_DEBUG; // 7 - case LogLevel::TRACE: - return LOG_DEBUG; // 7 - case LogLevel::HELP: - return LOG_DEBUG; // 7 - default: - return LOG_DEBUG; // 7 - } -} + inline int toJournalPriority(LogLevel logLevel) + { + switch(logLevel) + { + case LogLevel::ERROR: + return LOG_ERR; // 3 + case LogLevel::WARN: + return LOG_WARNING; // 4 + case LogLevel::INFO: + return LOG_INFO; // 6 + case LogLevel::DEBUG: + return LOG_DEBUG; // 7 + case LogLevel::TRACE: + return LOG_DEBUG; // 7 + case LogLevel::HELP: + return LOG_DEBUG; // 7 + default: + return LOG_DEBUG; // 7 + } + } -} // namespace + } // namespace -void SystemdJournalBackend::log(LogLevel logLevel, - const std::string& file, - const unsigned int& line, - const std::string& func, - const std::string& message) -{ - sd_journal_send("PRIORITY=%d", toJournalPriority(logLevel), - "CODE_FILE=%s", file.c_str(), - "CODE_LINE=%d", line, - "CODE_FUNC=%s", func.c_str(), - "MESSAGE=%s", message.c_str(), - NULL); -} + void SystemdJournalBackend::log(LogLevel logLevel, + const std::string& file, + const unsigned int& line, + const std::string& func, + const std::string& message) + { + sd_journal_send("PRIORITY=%d", toJournalPriority(logLevel), + "CODE_FILE=%s", file.c_str(), + "CODE_LINE=%d", line, + "CODE_FUNC=%s", func.c_str(), + "MESSAGE=%s", message.c_str(), + NULL); + } } // namespace logger #endif // HAVE_SYSTEMD_JOURNAL diff --git a/src/logger/backend-stderr.cpp b/src/logger/backend-stderr.cpp index 82e4c21..2088b5f 100644 --- a/src/logger/backend-stderr.cpp +++ b/src/logger/backend-stderr.cpp @@ -27,41 +27,44 @@ #include "logger/formatter.hpp" #if defined(HAVE_BOOST) - #include +#include #endif -namespace logger { - -void StderrBackend::log(LogLevel logLevel, - const std::string& file, - const unsigned int& line, - const std::string& func, - const std::string& message) +namespace logger { + + void StderrBackend::log(LogLevel logLevel, + const std::string& file, + const unsigned int& line, + const std::string& func, + const std::string& message) + { #if defined(HAVE_BOOST) - typedef boost::char_separator charSeparator; - typedef boost::tokenizer tokenizer; + typedef boost::char_separator charSeparator; + typedef boost::tokenizer tokenizer; - // example log string - // 06:52:35.123 [ERROR] src/util/fs.cpp:43 readFileContent: /file/file.txt is missing + // example log string + // 06:52:35.123 [ERROR] src/util/fs.cpp:43 readFileContent: /file/file.txt is missing - const std::string logColor = LogFormatter::getConsoleColor(logLevel); - const std::string defaultColor = LogFormatter::getDefaultConsoleColor(); - const std::string header = LogFormatter::getHeader(logLevel, file, line, func); - tokenizer tokens(message, charSeparator("\n")); - for (const auto& messageLine : tokens) { - if (!messageLine.empty()) { - fprintf(stderr, - "%s%s %s%s\n", - useColours ? logColor.c_str() : "", - header.c_str(), - messageLine.c_str(), - useColours ? defaultColor.c_str() : ""); - } - } + const std::string logColor = LogFormatter::getConsoleColor(logLevel); + const std::string defaultColor = LogFormatter::getDefaultConsoleColor(); + const std::string header = LogFormatter::getHeader(logLevel, file, line, func); + tokenizer tokens(message, charSeparator("\n")); + for(const auto& messageLine : tokens) + { + if(!messageLine.empty()) + { + fprintf(stderr, + "%s%s %s%s\n", + useColours ? logColor.c_str() : "", + header.c_str(), + messageLine.c_str(), + useColours ? defaultColor.c_str() : ""); + } + } #else - fprintf (stderr, "%s %s\n", LogFormatter::getHeader(logLevel, file, line, func).c_str(), message.c_str()); + fprintf(stderr, "%s %s\n", LogFormatter::getHeader(logLevel, file, line, func).c_str(), message.c_str()); #endif -} + } } // namespace logger diff --git a/src/logger/backend-syslog.cpp b/src/logger/backend-syslog.cpp index 42e8ca0..170de29 100644 --- a/src/logger/backend-syslog.cpp +++ b/src/logger/backend-syslog.cpp @@ -28,39 +28,42 @@ #include #include -namespace logger { +namespace logger +{ -namespace { + namespace + { -inline int toSyslogPriority(LogLevel logLevel) -{ - switch (logLevel) { - case LogLevel::ERROR: - return LOG_ERR; // 3 - case LogLevel::WARN: - return LOG_WARNING; // 4 - case LogLevel::INFO: - return LOG_INFO; // 6 - case LogLevel::DEBUG: - return LOG_DEBUG; // 7 - case LogLevel::TRACE: - return LOG_DEBUG; // 7 - case LogLevel::HELP: - return LOG_DEBUG; // 7 - default: - return LOG_DEBUG; // 7 - } -} + inline int toSyslogPriority(LogLevel logLevel) + { + switch(logLevel) + { + case LogLevel::ERROR: + return LOG_ERR; // 3 + case LogLevel::WARN: + return LOG_WARNING; // 4 + case LogLevel::INFO: + return LOG_INFO; // 6 + case LogLevel::DEBUG: + return LOG_DEBUG; // 7 + case LogLevel::TRACE: + return LOG_DEBUG; // 7 + case LogLevel::HELP: + return LOG_DEBUG; // 7 + default: + return LOG_DEBUG; // 7 + } + } -} // namespace + } // namespace -void SyslogBackend::log(LogLevel logLevel, - const std::string& file, - const unsigned int& line, - const std::string& func, - const std::string& message) -{ - syslog(toSyslogPriority(logLevel), "%s %s", LogFormatter::getHeader(logLevel, file, line, func).c_str(), message.c_str()); -} + void SyslogBackend::log(LogLevel logLevel, + const std::string& file, + const unsigned int& line, + const std::string& func, + const std::string& message) + { + syslog(toSyslogPriority(logLevel), "%s %s", LogFormatter::getHeader(logLevel, file, line, func).c_str(), message.c_str()); + } } // namespace logger diff --git a/src/logger/ccolor.cpp b/src/logger/ccolor.cpp index 9cc652d..f3eafec 100644 --- a/src/logger/ccolor.cpp +++ b/src/logger/ccolor.cpp @@ -27,15 +27,16 @@ #include -namespace logger { - -std::string getConsoleEscapeSequence(Attributes attr, Color color) +namespace logger { - char command[10]; - // Command is the control command to the terminal - snprintf(command, sizeof(command), "%c[%u;%um", 0x1B, (unsigned int)attr, (unsigned int)color); - return std::string(command); -} + std::string getConsoleEscapeSequence(Attributes attr, Color color) + { + char command[10]; + + // Command is the control command to the terminal + snprintf(command, sizeof(command), "%c[%u;%um", 0x1B, (unsigned int)attr, (unsigned int)color); + return std::string(command); + } } // namespace logger diff --git a/src/logger/formatter.cpp b/src/logger/formatter.cpp index 815a111..4d5cd20 100644 --- a/src/logger/formatter.cpp +++ b/src/logger/formatter.cpp @@ -33,99 +33,105 @@ #include #include -namespace logger { - -namespace { - -const int TIME_COLUMN_LENGTH = 12; -const int SEVERITY_COLUMN_LENGTH = 8; -const int THREAD_COLUMN_LENGTH = 3; -const int FILE_COLUMN_LENGTH = 60; - -std::atomic gNextThreadId(1); -thread_local unsigned int gThisThreadId(0); - -} // namespace - -unsigned int LogFormatter::getCurrentThread(void) -{ - unsigned int id = gThisThreadId; - if (id == 0) { - gThisThreadId = id = gNextThreadId++; - } - - return id; -} - -std::string LogFormatter::getCurrentTime(void) -{ - char time[TIME_COLUMN_LENGTH + 1]; - struct timeval tv; - gettimeofday(&tv, NULL); - struct tm* tm = localtime(&tv.tv_sec); - snprintf(time, - sizeof(time), - "%02d:%02d:%02d.%03d", - tm->tm_hour, - tm->tm_min, - tm->tm_sec, - int(tv.tv_usec / 1000)); - - return std::string(time); -} - -std::string LogFormatter::getConsoleColor(LogLevel logLevel) +namespace logger { - switch (logLevel) { - case LogLevel::ERROR: - return getConsoleEscapeSequence(Attributes::BOLD, Color::RED); - case LogLevel::WARN: - return getConsoleEscapeSequence(Attributes::BOLD, Color::YELLOW); - case LogLevel::INFO: - return getConsoleEscapeSequence(Attributes::BOLD, Color::BLUE); - case LogLevel::DEBUG: - return getConsoleEscapeSequence(Attributes::DEFAULT, Color::GREEN); - case LogLevel::TRACE: - return getConsoleEscapeSequence(Attributes::DEFAULT, Color::BLACK); - case LogLevel::HELP: - return getConsoleEscapeSequence(Attributes::BOLD, Color::MAGENTA); - default: - return getConsoleEscapeSequence(Attributes::DEFAULT, Color::DEFAULT); - } -} - -std::string LogFormatter::getDefaultConsoleColor(void) -{ - return getConsoleEscapeSequence(Attributes::DEFAULT, Color::DEFAULT); -} -std::string LogFormatter::stripProjectDir(const std::string& file, - const std::string& rootDir) -{ - // If rootdir is empty then return full name - if (rootDir.empty()) { - return file; - } - const std::string sourceDir = rootDir + "/"; - // If file does not belong to rootDir then also return full name - if (0 != file.compare(0, sourceDir.size(), sourceDir)) { - return file; - } - return file.substr(sourceDir.size()); -} - -std::string LogFormatter::getHeader(LogLevel logLevel, - const std::string& file, - const unsigned int& line, - const std::string& func) -{ - std::ostringstream logLine; - logLine << getCurrentTime() << ' ' - << std::left << std::setw(SEVERITY_COLUMN_LENGTH) << '[' + toString(logLevel) + ']' - << std::right << std::setw(THREAD_COLUMN_LENGTH) << getCurrentThread() << ": " - << std::left << std::setw(FILE_COLUMN_LENGTH) - << file + ':' + std::to_string(line) + ' ' + func + ':'; - return logLine.str(); -} + namespace + { + + const int TIME_COLUMN_LENGTH = 12; + const int SEVERITY_COLUMN_LENGTH = 8; + const int THREAD_COLUMN_LENGTH = 3; + const int FILE_COLUMN_LENGTH = 60; + + std::atomic gNextThreadId(1); + thread_local unsigned int gThisThreadId(0); + + } // namespace + + unsigned int LogFormatter::getCurrentThread(void) + { + unsigned int id = gThisThreadId; + if(id == 0) + { + gThisThreadId = id = gNextThreadId++; + } + + return id; + } + + std::string LogFormatter::getCurrentTime(void) + { + char time[TIME_COLUMN_LENGTH + 1]; + struct timeval tv; + gettimeofday(&tv, NULL); + struct tm* tm = localtime(&tv.tv_sec); + snprintf(time, + sizeof(time), + "%02d:%02d:%02d.%03d", + tm->tm_hour, + tm->tm_min, + tm->tm_sec, + int(tv.tv_usec / 1000)); + + return std::string(time); + } + + std::string LogFormatter::getConsoleColor(LogLevel logLevel) + { + switch(logLevel) + { + case LogLevel::ERROR: + return getConsoleEscapeSequence(Attributes::BOLD, Color::RED); + case LogLevel::WARN: + return getConsoleEscapeSequence(Attributes::BOLD, Color::YELLOW); + case LogLevel::INFO: + return getConsoleEscapeSequence(Attributes::BOLD, Color::BLUE); + case LogLevel::DEBUG: + return getConsoleEscapeSequence(Attributes::DEFAULT, Color::GREEN); + case LogLevel::TRACE: + return getConsoleEscapeSequence(Attributes::DEFAULT, Color::BLACK); + case LogLevel::HELP: + return getConsoleEscapeSequence(Attributes::BOLD, Color::MAGENTA); + default: + return getConsoleEscapeSequence(Attributes::DEFAULT, Color::DEFAULT); + } + } + + std::string LogFormatter::getDefaultConsoleColor(void) + { + return getConsoleEscapeSequence(Attributes::DEFAULT, Color::DEFAULT); + } + + std::string LogFormatter::stripProjectDir(const std::string& file, + const std::string& rootDir) + { + // If rootdir is empty then return full name + if(rootDir.empty()) + { + return file; + } + const std::string sourceDir = rootDir + "/"; + // If file does not belong to rootDir then also return full name + if(0 != file.compare(0, sourceDir.size(), sourceDir)) + { + return file; + } + return file.substr(sourceDir.size()); + } + + std::string LogFormatter::getHeader(LogLevel logLevel, + const std::string& file, + const unsigned int& line, + const std::string& func) + { + std::ostringstream logLine; + logLine << getCurrentTime() << ' ' + << std::left << std::setw(SEVERITY_COLUMN_LENGTH) << '[' + toString(logLevel) + ']' + << std::right << std::setw(THREAD_COLUMN_LENGTH) << getCurrentThread() << ": " + << std::left << std::setw(FILE_COLUMN_LENGTH) + << file + ':' + std::to_string(line) + ' ' + func + ':'; + return logLine.str(); + } } // namespace logger diff --git a/src/logger/level.cpp b/src/logger/level.cpp index 156d909..ee53cf8 100644 --- a/src/logger/level.cpp +++ b/src/logger/level.cpp @@ -27,69 +27,109 @@ #include #if defined(HAVE_BOOST) - #include +#include -namespace logger { - -LogLevel parseLogLevel(const std::string& level) +namespace logger { - if (boost::iequals(level, "ERROR")) { - return LogLevel::ERROR; - } else if (boost::iequals(level, "WARN")) { - return LogLevel::WARN; - } else if (boost::iequals(level, "INFO")) { - return LogLevel::INFO; - } else if (boost::iequals(level, "DEBUG")) { - return LogLevel::DEBUG; - } else if (boost::iequals(level, "TRACE")) { - return LogLevel::TRACE; - } else if (boost::iequals(level, "HELP")) { - return LogLevel::HELP; - } else { - throw std::runtime_error("Invalid LogLevel to parse"); - } -} + + LogLevel parseLogLevel(const std::string& level) + { + if(boost::iequals(level, "ERROR")) + { + return LogLevel::ERROR; + } + else + if(boost::iequals(level, "WARN")) + { + return LogLevel::WARN; + } + else + if(boost::iequals(level, "INFO")) + { + return LogLevel::INFO; + } + else + if(boost::iequals(level, "DEBUG")) + { + return LogLevel::DEBUG; + } + else + if(boost::iequals(level, "TRACE")) + { + return LogLevel::TRACE; + } + else + if(boost::iequals(level, "HELP")) + { + return LogLevel::HELP; + } + else + { + throw std::runtime_error("Invalid LogLevel to parse"); + } + } #else #include -namespace logger { - -LogLevel parseLogLevel(const std::string& level) +namespace logger { - if (strcmp(level.c_str(), "ERROR")) { - return LogLevel::ERROR; - } else if (strcmp(level.c_str(), "WARN") == 0) { - return LogLevel::WARN; - } else if (strcmp(level.c_str(), "INFO") == 0) { - return LogLevel::INFO; - } else if (strcmp(level.c_str(), "DEBUG") == 0) { - return LogLevel::DEBUG; - } else if (strcmp(level.c_str(), "TRACE") == 0) { - return LogLevel::TRACE; - } else if (strcmp(level.c_str(), "HELP") == 0) { - return LogLevel::HELP; - } else { - throw std::runtime_error("Invalid LogLevel to parse"); - } -} + + LogLevel parseLogLevel(const std::string& level) + { + if(strcmp(level.c_str(), "ERROR")) + { + return LogLevel::ERROR; + } + else + if(strcmp(level.c_str(), "WARN") == 0) + { + return LogLevel::WARN; + } + else + if(strcmp(level.c_str(), "INFO") == 0) + { + return LogLevel::INFO; + } + else + if(strcmp(level.c_str(), "DEBUG") == 0) + { + return LogLevel::DEBUG; + } + else + if(strcmp(level.c_str(), "TRACE") == 0) + { + return LogLevel::TRACE; + } + else + if(strcmp(level.c_str(), "HELP") == 0) + { + return LogLevel::HELP; + } + else + { + throw std::runtime_error("Invalid LogLevel to parse"); + } + } #endif -std::string toString(const LogLevel logLevel) -{ - switch (logLevel) { - case LogLevel::ERROR: - return "ERROR"; - case LogLevel::WARN: - return "WARN"; - case LogLevel::INFO: - return "INFO"; - case LogLevel::DEBUG: - return "DEBUG"; - case LogLevel::TRACE: - return "TRACE"; - case LogLevel::HELP: - return "HELP"; - default: - return "UNKNOWN"; - } -} + std::string toString(const LogLevel logLevel) + { + switch(logLevel) + { + case LogLevel::ERROR: + return "ERROR"; + case LogLevel::WARN: + return "WARN"; + case LogLevel::INFO: + return "INFO"; + case LogLevel::DEBUG: + return "DEBUG"; + case LogLevel::TRACE: + return "TRACE"; + case LogLevel::HELP: + return "HELP"; + default: + return "UNKNOWN"; + } + } } // namespace logger + diff --git a/src/logger/logger-scope.cpp b/src/logger/logger-scope.cpp index a977adc..38125d3 100644 --- a/src/logger/logger-scope.cpp +++ b/src/logger/logger-scope.cpp @@ -25,36 +25,39 @@ #include "logger/logger-scope.hpp" #include "logger/logger.hpp" -namespace logger { - -SStreamWrapper::operator std::string() const +namespace logger { - return mSStream.str(); -} -LoggerScope::LoggerScope(const std::string& file, - const unsigned int line, - const std::string& func, - const std::string& message, - const std::string& rootDir): - mFile(file), - mLine(line), - mFunc(func), - mMessage(message), - mRootDir(rootDir) -{ - if (logger::Logger::getLogLevel() <= logger::LogLevel::TRACE) { - logger::Logger::logMessage(logger::LogLevel::TRACE, "Entering: " + mMessage, - mFile, mLine, mFunc, mRootDir); - } -} + SStreamWrapper::operator std::string() const + { + return mSStream.str(); + } -LoggerScope::~LoggerScope() -{ - if (logger::Logger::getLogLevel() <= logger::LogLevel::TRACE) { - logger::Logger::logMessage(logger::LogLevel::TRACE, "Leaving: " + mMessage, - mFile, mLine, mFunc, mRootDir); - } -} + LoggerScope::LoggerScope(const std::string& file, + const unsigned int line, + const std::string& func, + const std::string& message, + const std::string& rootDir): + mFile(file), + mLine(line), + mFunc(func), + mMessage(message), + mRootDir(rootDir) + { + if(logger::Logger::getLogLevel() <= logger::LogLevel::TRACE) + { + logger::Logger::logMessage(logger::LogLevel::TRACE, "Entering: " + mMessage, + mFile, mLine, mFunc, mRootDir); + } + } + + LoggerScope::~LoggerScope() + { + if(logger::Logger::getLogLevel() <= logger::LogLevel::TRACE) + { + logger::Logger::logMessage(logger::LogLevel::TRACE, "Leaving: " + mMessage, + mFile, mLine, mFunc, mRootDir); + } + } } // namespace logger diff --git a/src/logger/logger.cpp b/src/logger/logger.cpp index ec0855b..53b96d5 100644 --- a/src/logger/logger.cpp +++ b/src/logger/logger.cpp @@ -30,47 +30,49 @@ #include #include -namespace logger { +namespace logger +{ -namespace { + namespace + { -volatile LogLevel gLogLevel = LogLevel::DEBUG; -std::unique_ptr gLogBackendPtr(new NullLogger()); -std::mutex gLogMutex; + volatile LogLevel gLogLevel = LogLevel::DEBUG; + std::unique_ptr gLogBackendPtr(new NullLogger()); + std::mutex gLogMutex; -} // namespace + } // namespace -void Logger::logMessage(LogLevel logLevel, - const std::string& message, - const std::string& file, - const unsigned int line, - const std::string& func, - const std::string& rootDir) -{ - std::string sfile = LogFormatter::stripProjectDir(file, rootDir); - std::unique_lock lock(gLogMutex); - gLogBackendPtr->log(logLevel, sfile, line, func, message); -} + void Logger::logMessage(LogLevel logLevel, + const std::string& message, + const std::string& file, + const unsigned int line, + const std::string& func, + const std::string& rootDir) + { + std::string sfile = LogFormatter::stripProjectDir(file, rootDir); + std::unique_lock lock(gLogMutex); + gLogBackendPtr->log(logLevel, sfile, line, func, message); + } -void Logger::setLogLevel(const LogLevel level) -{ - gLogLevel = level; -} + void Logger::setLogLevel(const LogLevel level) + { + gLogLevel = level; + } -void Logger::setLogLevel(const std::string& level) -{ - gLogLevel = parseLogLevel(level); -} + void Logger::setLogLevel(const std::string& level) + { + gLogLevel = parseLogLevel(level); + } -LogLevel Logger::getLogLevel(void) -{ - return gLogLevel; -} + LogLevel Logger::getLogLevel(void) + { + return gLogLevel; + } -void Logger::setLogBackend(LogBackend* pBackend) -{ - std::unique_lock lock(gLogMutex); - gLogBackendPtr.reset(pBackend); -} + void Logger::setLogBackend(LogBackend* pBackend) + { + std::unique_lock lock(gLogMutex); + gLogBackendPtr.reset(pBackend); + } } // namespace logger diff --git a/src/nether_CynaraBackend.cpp b/src/nether_CynaraBackend.cpp index 589387c..67405ae 100644 --- a/src/nether_CynaraBackend.cpp +++ b/src/nether_CynaraBackend.cpp @@ -27,154 +27,147 @@ #ifdef HAVE_CYNARA NetherCynaraBackend::NetherCynaraBackend(const NetherConfig &netherConfig) - : NetherPolicyBackend(netherConfig), currentCynaraDescriptor(0), - cynaraLastResult(CYNARA_API_UNKNOWN_ERROR) + : NetherPolicyBackend(netherConfig), currentCynaraDescriptor(0), + cynaraLastResult(CYNARA_API_UNKNOWN_ERROR) { - responseQueue.reserve(1024); + responseQueue.reserve(1024); } NetherCynaraBackend::~NetherCynaraBackend() { } -const bool NetherCynaraBackend::initialize() +bool NetherCynaraBackend::initialize() { - cynaraLastResult = cynara_async_initialize(&cynaraContext, NULL, &statusCallback, this); - if (cynaraLastResult != CYNARA_API_SUCCESS) - { - LOGE("Failed to initialize cynara client " << cynaraErrorCodeToString(cynaraLastResult)); - return (false); - } - - return (true); + cynaraLastResult = cynara_async_initialize(&cynaraContext, NULL, &statusCallback, this); + if(cynaraLastResult != CYNARA_API_SUCCESS) + { + LOGE("Failed to initialize cynara client " << cynaraErrorCodeToString(cynaraLastResult)); + return (false); + } + + return (true); } -void NetherCynaraBackend::statusCallback(int oldFd, int newFd, cynara_async_status status, void *data) +void NetherCynaraBackend::statusCallback(int , int newFd, cynara_async_status status, void *data) { - NetherCynaraBackend *backend = static_cast(data); + NetherCynaraBackend *backend = static_cast(data); - if (status == CYNARA_STATUS_FOR_READ) - backend->setCynaraDescriptor(newFd, NetherDescriptorStatus::readOnly); + if(status == CYNARA_STATUS_FOR_READ) + backend->setCynaraDescriptor(newFd, NetherDescriptorStatus::readOnly); - if (status == CYNARA_STATUS_FOR_RW) - backend->setCynaraDescriptor(newFd, NetherDescriptorStatus::readWrite); + if(status == CYNARA_STATUS_FOR_RW) + backend->setCynaraDescriptor(newFd, NetherDescriptorStatus::readWrite); } void NetherCynaraBackend::checkCallback(cynara_check_id check_id, - cynara_async_call_cause cause, - int response, - void *data) + cynara_async_call_cause cause, + int response, + void *data) { - NetherCynaraBackend *backend = static_cast(data); + NetherCynaraBackend *backend = static_cast(data); - if (cause == CYNARA_CALL_CAUSE_ANSWER) - backend->setCynaraVerdict (check_id, response); - else - LOGI("unknown reason for call cause="<< cause <<" response="<< response); + if(cause == CYNARA_CALL_CAUSE_ANSWER) + backend->setCynaraVerdict(check_id, response); + else + LOGI("unknown reason for call cause="<< cause <<" response="<< response); } -const bool NetherCynaraBackend::enqueueVerdict (const NetherPacket &packet) +bool NetherCynaraBackend::enqueueVerdict(const NetherPacket &packet) { - char user[NETHER_MAX_USER_LEN]; - cynara_check_id checkId; - - snprintf (user, sizeof(user), "%d", packet.uid); - - cynaraLastResult = cynara_async_check_cache(cynaraContext, packet.securityContext.c_str(), "", user, NETHER_CYNARA_INTERNET_PRIVILEGE); - - LOGD ("cynara_async_check_cache ctx=" << packet.securityContext.c_str() << " user=" << user << " privilege=" << NETHER_CYNARA_INTERNET_PRIVILEGE); - - switch (cynaraLastResult) - { - case CYNARA_API_ACCESS_ALLOWED: - LOGD(cynaraErrorCodeToString(cynaraLastResult).c_str()); - return (castVerdict(packet, NetherVerdict::allow)); - - case CYNARA_API_ACCESS_DENIED: - LOGD(cynaraErrorCodeToString(cynaraLastResult).c_str()); - return (castVerdict(packet, NetherVerdict::deny)); - - case CYNARA_API_CACHE_MISS: - cynaraLastResult = cynara_async_create_request(cynaraContext, - packet.securityContext.c_str(), - "", - user, - NETHER_CYNARA_INTERNET_PRIVILEGE, - &checkId, - &checkCallback, - this); - if (cynaraLastResult == CYNARA_API_SUCCESS) - { - responseQueue[checkId] = packet.id; - - return (true); - } - else if (cynaraLastResult == CYNARA_API_SERVICE_NOT_AVAILABLE) - { - LOGW("Cynara offline, fall back to another backend"); - return (false); - } - else - { - LOGW("Error on cynara request create after CYNARA_API_CACHE_MISS " << cynaraErrorCodeToString(cynaraLastResult)); - return (false); - } - - default: - LOGW("Error on cynara request create unhandled result from cynara_async_check_cache "<= 0) - { - responseQueue[checkId] = -1; + u_int32_t packetId = 0; + if((packetId = responseQueue[checkId]) >= 0) + { + responseQueue[checkId] = -1; - if (cynaraResult == CYNARA_API_ACCESS_ALLOWED) - castVerdict (packetId, NetherVerdict::allow); - else - castVerdict (packetId, NetherVerdict::deny); + if(cynaraResult == CYNARA_API_ACCESS_ALLOWED) + castVerdict(packetId, NetherVerdict::allow); + else + castVerdict(packetId, NetherVerdict::deny); - return; - } + return; + } - LOGW("checkId=" << checkId << " has no assosiated packetId"); + LOGW("checkId=" << checkId << " has no assosiated packetId"); } -const bool NetherCynaraBackend::isValid() +int NetherCynaraBackend::getDescriptor() { - return ((cynaraLastResult == CYNARA_API_SUCCESS ? true : false) && cynaraContext); + return (currentCynaraDescriptor); } -const int NetherCynaraBackend::getDescriptor() +NetherDescriptorStatus NetherCynaraBackend::getDescriptorStatus() { - return (currentCynaraDescriptor); -} - -const NetherDescriptorStatus NetherCynaraBackend::getDescriptorStatus() -{ - return (currentCynaraDescriptorStatus); + return (currentCynaraDescriptorStatus); } void NetherCynaraBackend::setCynaraDescriptor(const int _currentCynaraDescriptor, const NetherDescriptorStatus _currentCynaraDescriptorStatus) { - currentCynaraDescriptorStatus = _currentCynaraDescriptorStatus; - currentCynaraDescriptor = _currentCynaraDescriptor; + currentCynaraDescriptorStatus = _currentCynaraDescriptorStatus; + currentCynaraDescriptor = _currentCynaraDescriptor; } -const bool NetherCynaraBackend::processEvents() +bool NetherCynaraBackend::processEvents() { - int ret = cynara_async_process(cynaraContext); + int ret = cynara_async_process(cynaraContext); - if (ret == CYNARA_API_SUCCESS) - return (true); + if(ret == CYNARA_API_SUCCESS) + return (true); - LOGW("cynara_async_process failed " << cynaraErrorCodeToString(ret)); - return (false); + LOGW("cynara_async_process failed " << cynaraErrorCodeToString(ret)); + return (false); } #endif diff --git a/src/nether_FileBackend.cpp b/src/nether_FileBackend.cpp index 289014c..2a69733 100644 --- a/src/nether_FileBackend.cpp +++ b/src/nether_FileBackend.cpp @@ -24,8 +24,8 @@ #include "nether_FileBackend.h" -NetherFileBackend::NetherFileBackend (const NetherConfig &netherConfig) - : NetherPolicyBackend(netherConfig) +NetherFileBackend::NetherFileBackend(const NetherConfig &netherConfig) + : NetherPolicyBackend(netherConfig) { } @@ -33,93 +33,92 @@ NetherFileBackend::~NetherFileBackend() { } -const bool NetherFileBackend::isValid() +bool NetherFileBackend::initialize() { - return (true); -} - -const bool NetherFileBackend::initialize() -{ - std::ifstream policyFile; - policyFile.open (netherConfig.backupBackendArgs, std::ifstream::in); + std::ifstream policyFile; + policyFile.open(netherConfig.backupBackendArgs, std::ifstream::in); - if (!policyFile) - { - LOGE("Can't open policy file at: " << netherConfig.backupBackendArgs); - return (false); - } + if(!policyFile) + { + LOGE("Can't open policy file at: " << netherConfig.backupBackendArgs); + return (false); + } - return (parsePolicyFile(policyFile)); + return (parsePolicyFile(policyFile)); } -const bool NetherFileBackend::reload() +bool NetherFileBackend::reload() { - return (initialize()); + return (initialize()); } -const bool NetherFileBackend::enqueueVerdict(const NetherPacket &packet) +bool NetherFileBackend::enqueueVerdict(const NetherPacket &packet) { - for (auto &policyIterator : policy) - { - if ( - ( (policyIterator.uid == packet.uid) || policyIterator.uid == NETHER_INVALID_UID ) && - ( (policyIterator.gid == packet.gid) || policyIterator.gid == NETHER_INVALID_GID ) && - ( (policyIterator.securityContext == packet.securityContext) || policyIterator.securityContext.empty() ) - ) - { - LOGD("policy match " << dumpPolicyEntry(policyIterator)); - return (castVerdict(packet, policyIterator.verdict)); - } - } - - return (castVerdict(packet, netherConfig.defaultVerdict)); + for(auto &policyIterator : policy) + { + if( + ((policyIterator.uid == packet.uid) || policyIterator.uid == NETHER_INVALID_UID) && + ((policyIterator.gid == packet.gid) || policyIterator.gid == NETHER_INVALID_GID) && + ((policyIterator.securityContext == packet.securityContext) || policyIterator.securityContext.empty()) + ) + { + LOGD("policy match " << dumpPolicyEntry(policyIterator)); + return (castVerdict(packet, policyIterator.verdict)); + } + } + + return (castVerdict(packet, netherConfig.defaultVerdict)); } -const bool NetherFileBackend::parsePolicyFile(std::ifstream &policyFile) +bool NetherFileBackend::parsePolicyFile(std::ifstream &policyFile) { - std::string line; - std::vector tokens; - policy.clear(); - - while (!policyFile.eof()) - { - getline(policyFile, line); - if (line[0] == '#' || line.empty() || !line.find(NETHER_POLICY_CREDS_DELIM, 0)) - continue; - - tokens = split (line, NETHER_POLICY_CREDS_DELIM); - - if (tokens.size() > 0) - { - PolicyEntry entry { tokens[uidT].empty() ? NETHER_INVALID_UID : (uid_t)strtol(tokens[uidT].c_str(), NULL, 10), /* uid */ - tokens[gidT].empty() ? NETHER_INVALID_GID : (gid_t)strtol(tokens[gidT].c_str(), NULL, 10), /* gid */ - tokens[secctxT], /* security context */ - stringToVerdict((char *)tokens[verdictT].c_str()) /* verdict */ - }; - - LOGD("\t"< tokens; + policy.clear(); + + while(!policyFile.eof()) + { + getline(policyFile, line); + if(line[0] == '#' || line.empty() || !line.find(NETHER_POLICY_CREDS_DELIM, 0)) + continue; + + tokens = split(line, NETHER_POLICY_CREDS_DELIM); + + if(tokens.size() > 0) + { + PolicyEntry entry { tokens[PolicyFileTokens::uidToken].empty() ? + NETHER_INVALID_UID : + (uid_t)strtol(tokens[PolicyFileTokens::uidToken].c_str(), NULL, 10), + tokens[PolicyFileTokens::gidToken].empty() ? + NETHER_INVALID_GID : + (gid_t)strtol(tokens[PolicyFileTokens::gidToken].c_str(), NULL, 10), + tokens[PolicyFileTokens::secctxToken], + stringToVerdict((char *)tokens[PolicyFileTokens::verdictToken].c_str()) + }; + + LOGD("\t"< NetherFileBackend::split(const std::string &str, const std::string &delim) { - std::vector tokens; - size_t start = 0, end = 0; + std::vector tokens; + size_t start = 0, end = 0; - while (end != std::string::npos) - { - end = str.find(delim, start); + while(end != std::string::npos) + { + end = str.find(delim, start); - // If at end, use length=maxLength. Else use length=end-start. - tokens.push_back(str.substr(start, (end == std::string::npos) ? std::string::npos : end - start)); + // If at end, use length=maxLength. Else use length=end-start. + tokens.push_back(str.substr(start, (end == std::string::npos) ? std::string::npos : end - start)); - // If at end, use start=maxSize. Else use start=end+delimiter. - start = ((end > (std::string::npos - delim.size())) ? std::string::npos : end + delim.size()); - } + // If at end, use start=maxSize. Else use start=end+delimiter. + start = ((end > (std::string::npos - delim.size())) ? std::string::npos : end + delim.size()); + } - return (tokens); + return (tokens); } diff --git a/src/nether_Main.cpp b/src/nether_Main.cpp index 8914a20..d5883e9 100644 --- a/src/nether_Main.cpp +++ b/src/nether_Main.cpp @@ -32,218 +32,218 @@ void showHelp(char *arg); int main(int argc, char *argv[]) { - int optionIndex, c; - struct NetherConfig netherConfig; + int optionIndex, c; + struct NetherConfig netherConfig; - static struct option longOptions[] = - { - #if defined(HAVE_AUDIT) - {"enable-audit", no_argument, &netherConfig.enableAudit, 0}, + static struct option longOptions[] = + { +#if defined(HAVE_AUDIT) + {"enable-audit", no_argument, &netherConfig.enableAudit, 0}, #endif - {"daemon", no_argument, &netherConfig.daemonMode, 0}, - {"no-rules", no_argument, &netherConfig.noRules, 0}, - {"log", required_argument, 0, 'l'}, - {"log-args", required_argument, 0, 'L'}, - {"default-verdict", required_argument, 0, 'V'}, - {"primary-backend", required_argument, 0, 'p'}, - {"primary-backend-args", required_argument, 0, 'P'}, - {"backup-backend", required_argument, 0, 'b'}, - {"backup-backend-args", required_argument, 0, 'B'}, - {"queue-num", required_argument, 0, 'q'}, - {"mark-deny", required_argument, 0, 'm'}, - {"mark-allow-log", required_argument, 0, 'M'}, - {"rules-path", required_argument, 0, 'r'}, - {"iptables-restore-path", required_argument, 0, 'i'}, - {"help", no_argument, 0, 'h'}, - {0, 0, 0, 0} - }; - - while (1) - { - c = getopt_long (argc, argv, ":daxl:L:V:p:P:b:B:q:m:M:a:r:i:h", longOptions, &optionIndex); - - if (c == -1) - break; - - switch (c) - { - case 0: - break; - - case 'd': - netherConfig.daemonMode = 1; - break; - case 'x': - netherConfig.noRules = 1; - break; - - #if defined(HAVE_AUDIT) - case 'a': - netherConfig.enableAudit = 1; - break; + {"daemon", no_argument, &netherConfig.daemonMode, 0}, + {"no-rules", no_argument, &netherConfig.noRules, 0}, + {"log", required_argument, 0, 'l'}, + {"log-args", required_argument, 0, 'L'}, + {"default-verdict", required_argument, 0, 'V'}, + {"primary-backend", required_argument, 0, 'p'}, + {"primary-backend-args", required_argument, 0, 'P'}, + {"backup-backend", required_argument, 0, 'b'}, + {"backup-backend-args", required_argument, 0, 'B'}, + {"queue-num", required_argument, 0, 'q'}, + {"mark-deny", required_argument, 0, 'm'}, + {"mark-allow-log", required_argument, 0, 'M'}, + {"rules-path", required_argument, 0, 'r'}, + {"iptables-restore-path", required_argument, 0, 'i'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + + while(1) + { + c = getopt_long(argc, argv, ":daxl:L:V:p:P:b:B:q:m:M:a:r:i:h", longOptions, &optionIndex); + + if(c == -1) + break; + + switch(c) + { + case 0: + break; + + case 'd': + netherConfig.daemonMode = 1; + break; + case 'x': + netherConfig.noRules = 1; + break; + +#if defined(HAVE_AUDIT) + case 'a': + netherConfig.enableAudit = 1; + break; #endif - case 'l': - netherConfig.logBackend = stringToLogBackendType(optarg); - break; - - case 'L': - netherConfig.logBackendArgs = optarg; - break; - - case 'V': - netherConfig.defaultVerdict = stringToVerdict (optarg); - break; - - case 'p': - netherConfig.primaryBackendType = stringToBackendType (optarg); - break; - - case 'P': - netherConfig.primaryBackendArgs = optarg; - break; - - case 'b': - netherConfig.backupBackendType = stringToBackendType (optarg); - break; - - case 'B': - netherConfig.backupBackendArgs = optarg; - break; - - case 'q': - if (atoi(optarg) < 0 || atoi(optarg) >= 65535) - { - cerr << "Queue number is invalid (must be >= 0 and < 65535): " << atoi(optarg); - exit (1); - } - netherConfig.queueNumber = atoi(optarg); - break; - - case 'm': - if (atoi(optarg) <= 0 || atoi(optarg) >= 255) - { - cerr << "Packet mark for DENY is invalid (must be > 0 and < 255): " << atoi(optarg); - exit (1); - } - netherConfig.markDeny = atoi(optarg); - break; - - case 'M': - if (atoi(optarg) <= 0 || atoi(optarg) >= 255) - { - cerr << "Packet mark for ALLOW_LOG is invalid (must be > 0 and < 255): " << atoi(optarg); - exit (1); - } - netherConfig.markAllowAndLog = atoi(optarg); - break; - - case 'r': - netherConfig.rulesPath = optarg; - break; - - case 'i': - netherConfig.iptablesRestorePath = optarg; - break; - - case 'h': - showHelp (argv[0]); - exit (1); - } - } - switch (netherConfig.logBackend) - { - case NetherLogBackendType::stderrBackend: - logger::Logger::setLogBackend (new logger::StderrBackend(false)); - break; - case NetherLogBackendType::syslogBackend: - logger::Logger::setLogBackend (new logger::SyslogBackend()); - break; - case NetherLogBackendType::logfileBackend: - logger::Logger::setLogBackend (new logger::FileBackend(netherConfig.logBackendArgs)); - break; + case 'l': + netherConfig.logBackend = stringToLogBackendType(optarg); + break; + + case 'L': + netherConfig.logBackendArgs = optarg; + break; + + case 'V': + netherConfig.defaultVerdict = stringToVerdict(optarg); + break; + + case 'p': + netherConfig.primaryBackendType = stringToBackendType(optarg); + break; + + case 'P': + netherConfig.primaryBackendArgs = optarg; + break; + + case 'b': + netherConfig.backupBackendType = stringToBackendType(optarg); + break; + + case 'B': + netherConfig.backupBackendArgs = optarg; + break; + + case 'q': + if(atoi(optarg) < 0 || atoi(optarg) >= 65535) + { + cerr << "Queue number is invalid (must be >= 0 and < 65535): " << atoi(optarg); + exit(1); + } + netherConfig.queueNumber = atoi(optarg); + break; + + case 'm': + if(atoi(optarg) <= 0 || atoi(optarg) >= 255) + { + cerr << "Packet mark for DENY is invalid (must be > 0 and < 255): " << atoi(optarg); + exit(1); + } + netherConfig.markDeny = atoi(optarg); + break; + + case 'M': + if(atoi(optarg) <= 0 || atoi(optarg) >= 255) + { + cerr << "Packet mark for ALLOW_LOG is invalid (must be > 0 and < 255): " << atoi(optarg); + exit(1); + } + netherConfig.markAllowAndLog = atoi(optarg); + break; + + case 'r': + netherConfig.rulesPath = optarg; + break; + + case 'i': + netherConfig.iptablesRestorePath = optarg; + break; + + case 'h': + showHelp(argv[0]); + exit(1); + } + } + switch(netherConfig.logBackend) + { + case NetherLogBackendType::stderrBackend: + logger::Logger::setLogBackend(new logger::StderrBackend(false)); + break; + case NetherLogBackendType::syslogBackend: + logger::Logger::setLogBackend(new logger::SyslogBackend()); + break; + case NetherLogBackendType::logfileBackend: + logger::Logger::setLogBackend(new logger::FileBackend(netherConfig.logBackendArgs)); + break; #if defined(HAVE_SYSTEMD_JOURNAL) - case NetherLogBackendType::journalBackend: - logger::Logger::setLogBackend (new logger::SystemdJournalBackend()); - break; + case NetherLogBackendType::journalBackend: + logger::Logger::setLogBackend(new logger::SystemdJournalBackend()); + break; #endif - default: - logger::Logger::setLogBackend (new logger::StderrBackend(false)); - break; - } + default: + logger::Logger::setLogBackend(new logger::StderrBackend(false)); + break; + } - LOGD("NETHER OPTIONS:" + LOGD("NETHER OPTIONS:" #if defined(_DEBUG) - << " debug" + << " debug" #endif - << " daemon=" << netherConfig.daemonMode - << " queue=" << netherConfig.queueNumber); - LOGD("primary-backend=" << backendTypeToString (netherConfig.primaryBackendType) - << " primary-backend-args=" << netherConfig.primaryBackendArgs); - LOGD("backup-backend=" << backendTypeToString (netherConfig.backupBackendType) - << " backup-backend-args=" << netherConfig.backupBackendArgs); - LOGD("default-verdict=" << verdictToString(netherConfig.defaultVerdict) - << " mark-deny=" << (int)netherConfig.markDeny - << " mark-allow-log=" << (int)netherConfig.markAllowAndLog); - LOGD("log-backend=" << logBackendTypeToString(netherConfig.logBackend) - << " log-backend-args=" << netherConfig.logBackendArgs); - LOGD("enable-audit=" << (netherConfig.enableAudit ? "yes" : "no") - << " rules-path=" << netherConfig.rulesPath); - LOGD("no-rules=" << (netherConfig.noRules ? "yes" : "no") - << " iptables-restore-path=" << netherConfig.iptablesRestorePath); - - NetherManager manager (netherConfig); - - if (!manager.initialize()) - { - LOGE("NetherManager failed to initialize, exiting"); - return (1); - } - - if (netherConfig.daemonMode) - { - if (!runAsDaemon()) - { - LOGE("Failed to run as daemon: " << strerror(errno)); - exit (1); - } - } - - manager.process(); - - return (0); + << " daemon=" << netherConfig.daemonMode + << " queue=" << netherConfig.queueNumber); + LOGD("primary-backend=" << backendTypeToString(netherConfig.primaryBackendType) + << " primary-backend-args=" << netherConfig.primaryBackendArgs); + LOGD("backup-backend=" << backendTypeToString(netherConfig.backupBackendType) + << " backup-backend-args=" << netherConfig.backupBackendArgs); + LOGD("default-verdict=" << verdictToString(netherConfig.defaultVerdict) + << " mark-deny=" << (int)netherConfig.markDeny + << " mark-allow-log=" << (int)netherConfig.markAllowAndLog); + LOGD("log-backend=" << logBackendTypeToString(netherConfig.logBackend) + << " log-backend-args=" << netherConfig.logBackendArgs); + LOGD("enable-audit=" << (netherConfig.enableAudit ? "yes" : "no") + << " rules-path=" << netherConfig.rulesPath); + LOGD("no-rules=" << (netherConfig.noRules ? "yes" : "no") + << " iptables-restore-path=" << netherConfig.iptablesRestorePath); + + NetherManager manager(netherConfig); + + if(!manager.initialize()) + { + LOGE("NetherManager failed to initialize, exiting"); + return (1); + } + + if(netherConfig.daemonMode) + { + if(!runAsDaemon()) + { + LOGE("Failed to run as daemon: " << strerror(errno)); + exit(1); + } + } + + manager.process(); + + return (0); } void showHelp(char *arg) { - cout<< "Usage:\t"<< arg << " [OPTIONS]\n\n"; - cout<< " -d,--daemon\t\t\t\tRun as daemon in the background (default:no)\n"; - cout<< " -x,--no-rules\t\t\t\tDon't load iptables rules on start (default:no)\n"; - cout<< " -l,--log=\t\t\tSet logging backend STDERR,SYSLOG"; + cout<< "Usage:\t"<< arg << " [OPTIONS]\n\n"; + cout<< " -d,--daemon\t\t\t\tRun as daemon in the background (default:no)\n"; + cout<< " -x,--no-rules\t\t\t\tDon't load iptables rules on start (default:no)\n"; + cout<< " -l,--log=\t\t\tSet logging backend STDERR,SYSLOG"; #if defined(HAVE_SYSTEMD_JOURNAL) - cout << ",JOURNAL\n"; + cout << ",JOURNAL\n"; #endif - cout<< "(default:"<< logBackendTypeToString(NETHER_LOG_BACKEND) << ")\n"; - cout<< " -L,--log-args=\t\tSet logging backend arguments\n"; - cout<< " -V,--verdict=\t\tWhat verdict to cast when policy backend is not available\n\t\t\t\t\tACCEPT,ALLOW_LOG,DENY (default:"<\t\tPrimary policy backend\n\t\t\t\t\t"; + cout<< "(default:"<< logBackendTypeToString(NETHER_LOG_BACKEND) << ")\n"; + cout<< " -L,--log-args=\t\tSet logging backend arguments\n"; + cout<< " -V,--verdict=\t\tWhat verdict to cast when policy backend is not available\n\t\t\t\t\tACCEPT,ALLOW_LOG,DENY (default:"<\t\tPrimary policy backend\n\t\t\t\t\t"; #if defined(HAVE_CYNARA) - cout << "CYNARA"; + cout << "CYNARA"; #endif - cout<< ",FILE,NONE (defualt:"<< backendTypeToString(NETHER_PRIMARY_BACKEND)<<")\n"; - cout<< " -P,--primary-backend-args=\tPrimary policy backend arguments\n"; - cout<< " -b,--backup-backend=\t\tBackup policy backend\n\t\t\t\t\t"; + cout<< ",FILE,NONE (defualt:"<< backendTypeToString(NETHER_PRIMARY_BACKEND)<<")\n"; + cout<< " -P,--primary-backend-args=\tPrimary policy backend arguments\n"; + cout<< " -b,--backup-backend=\t\tBackup policy backend\n\t\t\t\t\t"; #if defined(HAVE_CYNARA) - cout<< "CYNARA"; + cout<< "CYNARA"; #endif - cout<< ",FILE,NONE (defualt:"<< backendTypeToString(NETHER_BACKUP_BACKEND)<< ")\n"; - cout<< " -B,--backup-backend-args=\tBackup policy backend arguments (default:" << NETHER_POLICY_FILE << ")\n"; - cout<< " -q,--queue-num=\t\tNFQUEUE queue number to use for receiving packets\n"; - cout<< " -m,--mark-deny=\t\t\tPacket mark to use for DENY verdicts (default:"<< NETLINK_DROP_MARK << ")\n"; - cout<< " -M,--mark-allow-log=\t\tPacket mark to use for ALLOW_LOG verdicts (default:" << NETLINK_ALLOWLOG_MARK << ")\n"; + cout<< ",FILE,NONE (defualt:"<< backendTypeToString(NETHER_BACKUP_BACKEND)<< ")\n"; + cout<< " -B,--backup-backend-args=\tBackup policy backend arguments (default:" << NETHER_POLICY_FILE << ")\n"; + cout<< " -q,--queue-num=\t\tNFQUEUE queue number to use for receiving packets\n"; + cout<< " -m,--mark-deny=\t\t\tPacket mark to use for DENY verdicts (default:"<< NETLINK_DROP_MARK << ")\n"; + cout<< " -M,--mark-allow-log=\t\tPacket mark to use for ALLOW_LOG verdicts (default:" << NETLINK_ALLOWLOG_MARK << ")\n"; #if defined(HAVE_AUDIT) - cout<< " -a,--enable-audit\t\t\tEnable the auditing subsystem (default: no)\n"; + cout<< " -a,--enable-audit\t\t\tEnable the auditing subsystem (default: no)\n"; #endif - cout<< " -r,--rules-path=\t\tPath to iptables rules file (default:" << NETHER_RULES_PATH << ")\n"; - cout<< " -i,--iptables-restore-path=\tPath to iptables-restore command (default:" << NETHER_IPTABLES_RESTORE_PATH << ")\n"; - cout<< " -h,--help\t\t\t\tshow help information\n"; + cout<< " -r,--rules-path=\t\tPath to iptables rules file (default:" << NETHER_RULES_PATH << ")\n"; + cout<< " -i,--iptables-restore-path=\tPath to iptables-restore command (default:" << NETHER_IPTABLES_RESTORE_PATH << ")\n"; + cout<< " -h,--help\t\t\t\tshow help information\n"; } diff --git a/src/nether_Manager.cpp b/src/nether_Manager.cpp index 581296a..21f5d25 100644 --- a/src/nether_Manager.cpp +++ b/src/nether_Manager.cpp @@ -28,329 +28,333 @@ #include "nether_DummyBackend.h" NetherManager::NetherManager(const NetherConfig &_netherConfig) - : netherConfig(_netherConfig), - netherPrimaryPolicyBackend(nullptr), - netherBackupPolicyBackend(nullptr), - netherFallbackPolicyBackend(nullptr) + : netherPrimaryPolicyBackend(nullptr), + netherBackupPolicyBackend(nullptr), + netherFallbackPolicyBackend(nullptr), + netherConfig(_netherConfig) { - netherNetlink = std::unique_ptr (new NetherNetlink(netherConfig)); - netherNetlink->setListener (this); + netherNetlink = std::unique_ptr (new NetherNetlink(netherConfig)); + netherNetlink->setListener(this); - netherPrimaryPolicyBackend = std::unique_ptr (getPolicyBackend (netherConfig)); - netherPrimaryPolicyBackend->setListener (this); + netherPrimaryPolicyBackend = std::unique_ptr (getPolicyBackend(netherConfig)); + netherPrimaryPolicyBackend->setListener(this); - netherBackupPolicyBackend = std::unique_ptr (getPolicyBackend (netherConfig, false)); - netherBackupPolicyBackend->setListener (this); + netherBackupPolicyBackend = std::unique_ptr (getPolicyBackend(netherConfig, false)); + netherBackupPolicyBackend->setListener(this); - netherFallbackPolicyBackend = std::unique_ptr (new NetherDummyBackend(netherConfig)); + netherFallbackPolicyBackend = std::unique_ptr (new NetherDummyBackend(netherConfig)); } NetherManager::~NetherManager() { - close (signalDescriptor); + close(signalDescriptor); } -const bool NetherManager::initialize() +bool NetherManager::initialize() { - sigemptyset(&signalMask); - sigaddset(&signalMask, SIGHUP); - - if (sigprocmask(SIG_BLOCK, &signalMask, NULL) == -1) - { - LOGE("Failed to block signals sigprocmask()"); - return (false); - } - - signalDescriptor = signalfd(-1, &signalMask, 0); - if (signalDescriptor == -1) - { - LOGE("Failed acquire signalfd descriptor"); - return (false); - } - - if (netherConfig.noRules == 0 && restoreRules() == false) - { - LOGE("Failed to setup iptables rules"); - return (false); - } + sigemptyset(&signalMask); + sigaddset(&signalMask, SIGHUP); + + if(sigprocmask(SIG_BLOCK, &signalMask, NULL) == -1) + { + LOGE("Failed to block signals sigprocmask()"); + return (false); + } + + signalDescriptor = signalfd(-1, &signalMask, 0); + if(signalDescriptor == -1) + { + LOGE("Failed acquire signalfd descriptor"); + return (false); + } + + if(netherConfig.noRules == 0 && restoreRules() == false) + { + LOGE("Failed to setup iptables rules"); + return (false); + } #ifdef HAVE_AUDIT - if (netherConfig.enableAudit) - { - if ( (auditDescriptor = audit_open ()) == -1) - { - LOGE("Failed to open an audit netlink socket: " << strerror(errno)); - return (false); - } - - if (audit_set_enabled (auditDescriptor, 1) <= 0) - { - LOGE("Failed to enable auditing: " << strerror(errno)); - return (false); - } - else - { - LOGD("Auditing enabled"); - } - } + if(netherConfig.enableAudit) + { + if((auditDescriptor = audit_open()) == -1) + { + LOGE("Failed to open an audit netlink socket: " << strerror(errno)); + return (false); + } + + if(audit_set_enabled(auditDescriptor, 1) <= 0) + { + LOGE("Failed to enable auditing: " << strerror(errno)); + return (false); + } + else + { + LOGD("Auditing enabled"); + } + } #endif // HAVE_AUDIT - if (!netherNetlink->initialize()) - { - LOGE("Failed to initialize netlink subsystem, exiting"); - return (false); - } - - if (!netherPrimaryPolicyBackend->initialize()) - { - LOGE("Failed to initialize primary policy backend, exiting"); - return (false); - } - - if (!netherBackupPolicyBackend->initialize()) - { - LOGE("Failed to initialize backup backend, exiting"); - return (false); - } - - if ((netlinkDescriptor = netherNetlink->getDescriptor()) == -1) - { - LOGE("Netlink subsystem did not return a valid descriptor, exiting"); - return (false); - } - - if ((backendDescriptor = netherPrimaryPolicyBackend->getDescriptor()) == -1) - { - LOGI("Policy backend does not provide descriptor for select()"); - } - return (true); + if(!netherNetlink->initialize()) + { + LOGE("Failed to initialize netlink subsystem, exiting"); + return (false); + } + + if(!netherPrimaryPolicyBackend->initialize()) + { + LOGE("Failed to initialize primary policy backend, exiting"); + return (false); + } + + if(!netherBackupPolicyBackend->initialize()) + { + LOGE("Failed to initialize backup backend, exiting"); + return (false); + } + + if((netlinkDescriptor = netherNetlink->getDescriptor()) == -1) + { + LOGE("Netlink subsystem did not return a valid descriptor, exiting"); + return (false); + } + + if((backendDescriptor = netherPrimaryPolicyBackend->getDescriptor()) == -1) + { + LOGI("Policy backend does not provide descriptor for select()"); + } + return (true); } -const bool NetherManager::process() -{ - fd_set watchedReadDescriptorsSet, watchedWriteDescriptorsSet; - struct timeval timeoutSpecification; - - for (;;) - { - setupSelectSockets (watchedReadDescriptorsSet, watchedWriteDescriptorsSet, timeoutSpecification); - - if (select (FD_SETSIZE, &watchedReadDescriptorsSet, &watchedWriteDescriptorsSet, NULL, &timeoutSpecification) < 0) - { - LOGE("select error " << strerror(errno)); - return (false); - } - - if (FD_ISSET(signalDescriptor, &watchedReadDescriptorsSet)) - { - handleSignal(); - } - if (FD_ISSET(netlinkDescriptor, &watchedReadDescriptorsSet)) - { - if (!handleNetlinkpacket()) - break; - } - else if (FD_ISSET(backendDescriptor, &watchedReadDescriptorsSet) || FD_ISSET(backendDescriptor, &watchedWriteDescriptorsSet)) - { - netherPrimaryPolicyBackend->processEvents(); - } - else - { - LOGD("select() timeout"); - } - } +bool NetherManager::process() +{ + fd_set watchedReadDescriptorsSet, watchedWriteDescriptorsSet; + struct timeval timeoutSpecification; + + for(;;) + { + setupSelectSockets(watchedReadDescriptorsSet, watchedWriteDescriptorsSet, timeoutSpecification); + + if(select(FD_SETSIZE, &watchedReadDescriptorsSet, &watchedWriteDescriptorsSet, NULL, &timeoutSpecification) < 0) + { + LOGE("select error " << strerror(errno)); + return (false); + } + + if(FD_ISSET(signalDescriptor, &watchedReadDescriptorsSet)) + { + handleSignal(); + } + if(FD_ISSET(netlinkDescriptor, &watchedReadDescriptorsSet)) + { + if(!handleNetlinkpacket()) + break; + } + else + if(FD_ISSET(backendDescriptor, &watchedReadDescriptorsSet) || FD_ISSET(backendDescriptor, &watchedWriteDescriptorsSet)) + { + netherPrimaryPolicyBackend->processEvents(); + } + else + { + LOGD("select() timeout"); + } + } + + return (true); } void NetherManager::handleSignal() { - LOGD("received signal"); - ssize_t signalRead; - struct signalfd_siginfo signalfdSignalInfo; - - signalRead = read (signalDescriptor, &signalfdSignalInfo, sizeof(struct signalfd_siginfo)); - - if (signalRead != sizeof(struct signalfd_siginfo)) - { - LOGW("Received incomplete signal information, ignore"); - return; - } - - if (signalfdSignalInfo.ssi_signo == SIGHUP) - { - LOGI("SIGHUP received, reloading"); - if (!netherPrimaryPolicyBackend->reload()) - LOGW("primary backend failed to reload"); - if (!netherBackupPolicyBackend->reload()) - LOGW("backup backend failed to reload"); - if (!netherNetlink->reload()) - LOGW("netlink failed to reload"); - } + LOGD("received signal"); + ssize_t signalRead; + struct signalfd_siginfo signalfdSignalInfo; + + signalRead = read(signalDescriptor, &signalfdSignalInfo, sizeof(struct signalfd_siginfo)); + + if(signalRead != sizeof(struct signalfd_siginfo)) + { + LOGW("Received incomplete signal information, ignore"); + return; + } + + if(signalfdSignalInfo.ssi_signo == SIGHUP) + { + LOGI("SIGHUP received, reloading"); + if(!netherPrimaryPolicyBackend->reload()) + LOGW("primary backend failed to reload"); + if(!netherBackupPolicyBackend->reload()) + LOGW("backup backend failed to reload"); + if(!netherNetlink->reload()) + LOGW("netlink failed to reload"); + } } -const bool NetherManager::handleNetlinkpacket() +bool NetherManager::handleNetlinkpacket() { - LOGD("netlink descriptor active"); - int packetReadSize; - NetherPacket receivedPacket; - char packetBuffer[NETHER_PACKET_BUFFER_SIZE] __attribute__ ((aligned)); - - /* some data arrives on netlink, read it */ - if ((packetReadSize = recv(netlinkDescriptor, packetBuffer, sizeof(packetBuffer), 0)) >= 0) - { - /* try to process the packet using netfilter_queue library, fetch packet info - needed for making a decision about it */ - if (netherNetlink->processPacket (packetBuffer, packetReadSize)) - { - return (true); - } - else - { - /* if we can't process the incoming packets, it's bad. Let's exit now */ - LOGE("Failed to process netlink received packet, refusing to continue"); - return (false); - } - } - - if (packetReadSize < 0 && errno == ENOBUFS) - { - LOGI("NetherManager::process losing packets! [bad things might happen]"); - return (true); - } - - LOGE("NetherManager::process recv failed " << strerror(errno)); - return (false); + LOGD("netlink descriptor active"); + int packetReadSize; + NetherPacket receivedPacket; + char packetBuffer[NETHER_PACKET_BUFFER_SIZE] __attribute__((aligned)); + + /* some data arrives on netlink, read it */ + if((packetReadSize = recv(netlinkDescriptor, packetBuffer, sizeof(packetBuffer), 0)) >= 0) + { + /* try to process the packet using netfilter_queue library, fetch packet info + needed for making a decision about it */ + if(netherNetlink->processPacket(packetBuffer, packetReadSize)) + { + return (true); + } + else + { + /* if we can't process the incoming packets, it's bad. Let's exit now */ + LOGE("Failed to process netlink received packet, refusing to continue"); + return (false); + } + } + + if(packetReadSize < 0 && errno == ENOBUFS) + { + LOGI("NetherManager::process losing packets! [bad things might happen]"); + return (true); + } + + LOGE("NetherManager::process recv failed " << strerror(errno)); + return (false); } void NetherManager::setupSelectSockets(fd_set &watchedReadDescriptorsSet, fd_set &watchedWriteDescriptorsSet, struct timeval &timeoutSpecification) { - FD_ZERO (&watchedReadDescriptorsSet); - FD_ZERO (&watchedWriteDescriptorsSet); - - /* Always listen for signals */ - FD_SET (signalDescriptor, &watchedReadDescriptorsSet); - - if ((netlinkDescriptor = netherNetlink->getDescriptor()) >= 0) - { - FD_SET(netlinkDescriptor, &watchedReadDescriptorsSet); - } - - if ((backendDescriptor = netherPrimaryPolicyBackend->getDescriptor()) >= 0) - { - if (netherPrimaryPolicyBackend->getDescriptorStatus() == NetherDescriptorStatus::readOnly) - { - FD_SET(backendDescriptor, &watchedReadDescriptorsSet); - } - else if (netherPrimaryPolicyBackend->getDescriptorStatus() == NetherDescriptorStatus::readWrite) - { - FD_SET(backendDescriptor, &watchedReadDescriptorsSet); - FD_SET(backendDescriptor, &watchedWriteDescriptorsSet); - } - } - - timeoutSpecification.tv_sec = 240; - timeoutSpecification.tv_usec = 0; + FD_ZERO(&watchedReadDescriptorsSet); + FD_ZERO(&watchedWriteDescriptorsSet); + + /* Always listen for signals */ + FD_SET(signalDescriptor, &watchedReadDescriptorsSet); + + if((netlinkDescriptor = netherNetlink->getDescriptor()) >= 0) + { + FD_SET(netlinkDescriptor, &watchedReadDescriptorsSet); + } + + if((backendDescriptor = netherPrimaryPolicyBackend->getDescriptor()) >= 0) + { + if(netherPrimaryPolicyBackend->getDescriptorStatus() == NetherDescriptorStatus::readOnly) + { + FD_SET(backendDescriptor, &watchedReadDescriptorsSet); + } + else + if(netherPrimaryPolicyBackend->getDescriptorStatus() == NetherDescriptorStatus::readWrite) + { + FD_SET(backendDescriptor, &watchedReadDescriptorsSet); + FD_SET(backendDescriptor, &watchedWriteDescriptorsSet); + } + } + + timeoutSpecification.tv_sec = 240; + timeoutSpecification.tv_usec = 0; } NetherConfig &NetherManager::getConfig() { - return (netherConfig); + return (netherConfig); } NetherPolicyBackend *NetherManager::getPolicyBackend(const NetherConfig &netherConfig, const bool primary) { - switch (primary ? netherConfig.primaryBackendType : netherConfig.backupBackendType) - { - case NetherPolicyBackendType::cynaraBackend: + switch(primary ? netherConfig.primaryBackendType : netherConfig.backupBackendType) + { + case NetherPolicyBackendType::cynaraBackend: #ifdef HAVE_CYNARA - return new NetherCynaraBackend(netherConfig); + return new NetherCynaraBackend(netherConfig); #else - return new NetherDummyBackend(netherConfig); + return new NetherDummyBackend(netherConfig); #endif - case NetherPolicyBackendType::fileBackend: - return new NetherFileBackend(netherConfig); - case NetherPolicyBackendType::dummyBackend: - default: - return new NetherDummyBackend(netherConfig); - } + case NetherPolicyBackendType::fileBackend: + return new NetherFileBackend(netherConfig); + case NetherPolicyBackendType::dummyBackend: + default: + return new NetherDummyBackend(netherConfig); + } } -bool NetherManager::verdictCast (const u_int32_t packetId, const NetherVerdict verdict) +bool NetherManager::verdictCast(const u_int32_t packetId, const NetherVerdict verdict) { - if (netherNetlink) - { - netherNetlink->setVerdict(packetId, verdict); - } - else - { - LOGE("Netlink subsystem is invalid, can't decide on packet"); - return (false); - } - - return (true); + if(netherNetlink) + { + netherNetlink->setVerdict(packetId, verdict); + } + else + { + LOGE("Netlink subsystem is invalid, can't decide on packet"); + return (false); + } + + return (true); } -void NetherManager::packetReceived (const NetherPacket &packet) +void NetherManager::packetReceived(const NetherPacket &packet) { - LOGD(packetToString(packet).c_str()); - - if (netherPrimaryPolicyBackend && netherPrimaryPolicyBackend->enqueueVerdict (packet)) - { - LOGD("Primary policy accepted packet"); - return; - } - - if (netherBackupPolicyBackend && netherBackupPolicyBackend->enqueueVerdict (packet)) - { - LOGI("Primary policy backend failed, using backup policy backend"); - return; - } - - /* In this situation no policy backend wants to deal with this packet - there propably isn't any rule in either of them - - we need to make a generic decision based on whatever is hard-coded - or passed as a parameter to the service */ - LOGW("All policy backends failed, using DUMMY backend"); - netherFallbackPolicyBackend->enqueueVerdict (packet); + LOGD(packetToString(packet).c_str()); + + if(netherPrimaryPolicyBackend && netherPrimaryPolicyBackend->enqueueVerdict(packet)) + { + LOGD("Primary policy accepted packet"); + return; + } + + if(netherBackupPolicyBackend && netherBackupPolicyBackend->enqueueVerdict(packet)) + { + LOGI("Primary policy backend failed, using backup policy backend"); + return; + } + + /* In this situation no policy backend wants to deal with this packet + there propably isn't any rule in either of them + + we need to make a generic decision based on whatever is hard-coded + or passed as a parameter to the service */ + LOGW("All policy backends failed, using DUMMY backend"); + netherFallbackPolicyBackend->enqueueVerdict(packet); } -const bool NetherManager::restoreRules() +bool NetherManager::restoreRules() { - if (!isCommandAvailable(netherConfig.iptablesRestorePath)) - { - return (false); - } - - std::stringstream cmdline; - cmdline << netherConfig.iptablesRestorePath; - cmdline << " "; - cmdline << netherConfig.rulesPath; - - if (system (cmdline.str().c_str())) - { - LOGE("system() failed for: " << cmdline.str()); - return (false); - } - - LOGD("iptables-restore succeeded with rules from: " << netherConfig.rulesPath); - return (true); + if(!isCommandAvailable(netherConfig.iptablesRestorePath)) + { + return (false); + } + + std::stringstream cmdline; + cmdline << netherConfig.iptablesRestorePath; + cmdline << " "; + cmdline << netherConfig.rulesPath; + + if(system(cmdline.str().c_str())) + { + LOGE("system() failed for: " << cmdline.str()); + return (false); + } + + LOGD("iptables-restore succeeded with rules from: " << netherConfig.rulesPath); + return (true); } -const bool NetherManager::isCommandAvailable(const std::string &command) +bool NetherManager::isCommandAvailable(const std::string &command) { - struct stat iptablesRestoreStat; + struct stat iptablesRestoreStat; - if (stat(command.c_str(), &iptablesRestoreStat) == 0) - { - if (! iptablesRestoreStat.st_mode & S_IXUSR) - { - LOGE("Execute bit is not set for owner on:" << command); - return (false); - } + if(stat(command.c_str(), &iptablesRestoreStat) == 0) + { + if(! iptablesRestoreStat.st_mode & S_IXUSR) + { + LOGE("Execute bit is not set for owner on:" << command); + return (false); + } - return (true); - } + return (true); + } - LOGE("Failed to stat command at: " << command << " error: " << strerror(errno)); - return (false); + LOGE("Failed to stat command at: " << command << " error: " << strerror(errno)); + return (false); } diff --git a/src/nether_Netlink.cpp b/src/nether_Netlink.cpp index 1b98bfa..c0a9994 100644 --- a/src/nether_Netlink.cpp +++ b/src/nether_Netlink.cpp @@ -22,155 +22,149 @@ * @brief netlink handler class for nether */ -#include "nether_Netlink.h" - -NetherNetlink::NetherNetlink(NetherConfig &netherConfig) - : nfqHandle(nullptr), queueHandle(nullptr), nlif(nullptr), - queue(netherConfig.queueNumber), - NetherPacketProcessor(netherConfig) -{ -} - -NetherNetlink::~NetherNetlink() +#include "nether_Netlink.h" + +NetherNetlink::NetherNetlink(NetherConfig &netherConfig) + : NetherPacketProcessor(netherConfig), queueHandle(nullptr), nfqHandle(nullptr), nlif(nullptr), queue(netherConfig.queueNumber) +{ +} + +NetherNetlink::~NetherNetlink() { - if (queueHandle) nfq_destroy_queue(queueHandle); - if (nfqHandle) nfq_close(nfqHandle); -} - -const bool NetherNetlink::initialize() -{ - nfqHandle = nfq_open(); - - if (!nfqHandle) - { - LOGE("Error during nfq_open()"); - return (false); - } - - if (nfq_unbind_pf(nfqHandle, AF_INET) < 0) - { - LOGE("Error during nfq_unbind_pf() (no permission?)"); - return (false); - } - - if (nfq_bind_pf(nfqHandle, AF_INET) < 0) - { - LOGE("Error during nfq_bind_pf()"); - return (false); - } - - queueHandle = nfq_create_queue(nfqHandle, queue, &callback, this); - - if (!queueHandle) - { - LOGE("Error during nfq_create_queue()"); - return (false); - } - - if (nfq_set_queue_flags(queueHandle, NFQA_CFG_F_SECCTX, NFQA_CFG_F_SECCTX)) - LOGI("This kernel version does not allow to retrieve security context"); - - if (nfq_set_mode(queueHandle, NFQNL_COPY_PACKET, 0xffff) < 0) - { - LOGE("Can't set packet_copy mode"); - nfq_destroy_queue (queueHandle); - return (false); - } - - if (nfq_set_queue_flags(queueHandle, NFQA_CFG_F_UID_GID, NFQA_CFG_F_UID_GID)) - { - LOGE("This kernel version does not allow to retrieve process UID/GID"); - nfq_destroy_queue (queueHandle); - return (false); - } - - nlif = nlif_open(); - if (!nlif) - LOGI("Failed to initialize NLIF subsystem, interface information won't be available"); - - return (true); -} + if(queueHandle) nfq_destroy_queue(queueHandle); + if(nfqHandle) nfq_close(nfqHandle); +} + +bool NetherNetlink::initialize() +{ + nfqHandle = nfq_open(); + + if(!nfqHandle) + { + LOGE("Error during nfq_open()"); + return (false); + } + + if(nfq_unbind_pf(nfqHandle, AF_INET) < 0) + { + LOGE("Error during nfq_unbind_pf() (no permission?)"); + return (false); + } + + if(nfq_bind_pf(nfqHandle, AF_INET) < 0) + { + LOGE("Error during nfq_bind_pf()"); + return (false); + } + + queueHandle = nfq_create_queue(nfqHandle, queue, &callback, this); + + if(!queueHandle) + { + LOGE("Error during nfq_create_queue()"); + return (false); + } + + if(nfq_set_queue_flags(queueHandle, NFQA_CFG_F_SECCTX, NFQA_CFG_F_SECCTX)) + LOGI("This kernel version does not allow to retrieve security context"); + + if(nfq_set_mode(queueHandle, NFQNL_COPY_META, 0xffff) < 0) + { + LOGE("Can't set packet_copy mode"); + nfq_destroy_queue(queueHandle); + return (false); + } + + if(nfq_set_queue_flags(queueHandle, NFQA_CFG_F_UID_GID, NFQA_CFG_F_UID_GID)) + { + LOGE("This kernel version does not allow to retrieve process UID/GID"); + nfq_destroy_queue(queueHandle); + return (false); + } + + nlif = nlif_open(); + if(!nlif) + LOGI("Failed to initialize NLIF subsystem, interface information won't be available"); + + return (true); +} int NetherNetlink::getDescriptor() { - if (nfqHandle) - return (nfq_fd(nfqHandle)); - else - LOGE("nfq not initialized"); + if(nfqHandle) + return (nfq_fd(nfqHandle)); + else + LOGE("nfq not initialized"); + return (-1); } -const bool NetherNetlink::processPacket (char *packetBuffer, const int packetReadSize) +bool NetherNetlink::processPacket(char *packetBuffer, const int packetReadSize) { - if (nfq_handle_packet (nfqHandle, packetBuffer, packetReadSize)) - { - LOGE("nfq_handle_packet failed"); - return (false); - } + if(nfq_handle_packet(nfqHandle, packetBuffer, packetReadSize)) + { + LOGE("nfq_handle_packet failed"); + return (false); + } - return (true); + return (true); } - -int NetherNetlink::callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) + +int NetherNetlink::callback(struct nfq_q_handle *, struct nfgenmsg *, struct nfq_data *nfa, void *data) { - NetherNetlink *me = static_cast(data); - NetherPacket packet; - unsigned char *secctx; - int secctxSize = 0; - struct nfqnl_msg_packet_hdr *ph; - unsigned char *payload; - - if ((ph = nfq_get_msg_packet_hdr(nfa))) - { - packet.id = ntohl(ph->packet_id); - } - else - { - LOGI("Failed to get packet id"); - return (1); - } - - if (nfq_get_uid(nfa, &packet.uid) == 0) - LOGW("Failed to get uid for packet id=" << packet.id); - - nfq_get_gid(nfa, &packet.gid); - - secctxSize = nfq_get_secctx(nfa, &secctx); - - if (secctxSize > 0) - packet.securityContext = std::string ((char *)secctx, secctxSize); - else - LOGD("Failed to get security context for packet id=" << packet.id); - - if (nfq_get_payload(nfa, &payload) > 0) - decodePacket(packet, payload); - - me->processNetherPacket (packet); /* this call if from the NetherPacketProcessor class */ - - return (0); -} - -const bool NetherNetlink::isValid() -{ - return (nfqHandle && queueHandle); + NetherNetlink *me = static_cast(data); + NetherPacket packet; + unsigned char *secctx; + int secctxSize = 0; + struct nfqnl_msg_packet_hdr *ph; + unsigned char *payload; + + if((ph = nfq_get_msg_packet_hdr(nfa))) + { + packet.id = ntohl(ph->packet_id); + } + else + { + LOGI("Failed to get packet id"); + return (1); + } + + if(nfq_get_uid(nfa, &packet.uid) == 0) + LOGW("Failed to get uid for packet id=" << packet.id); + + nfq_get_gid(nfa, &packet.gid); + + secctxSize = nfq_get_secctx(nfa, &secctx); + + if(secctxSize > 0) + packet.securityContext = std::string((char *)secctx, secctxSize); + else + LOGD("Failed to get security context for packet id=" << packet.id); + + if(nfq_get_payload(nfa, &payload) > 0) + decodePacket(packet, payload); + + me->processNetherPacket(packet); /* this call if from the NetherPacketProcessor class */ + + return (0); } void NetherNetlink::setVerdict(const u_int32_t packetId, const NetherVerdict verdict) { - int ret = 0; - LOGD("id=" << packetId << " verdict=" << verdictToString(verdict)); - - if (verdict == NetherVerdict::allow) - ret = nfq_set_verdict (queueHandle, packetId, NF_ACCEPT, 0, NULL); - if (verdict == NetherVerdict::deny) - ret = nfq_set_verdict2 (queueHandle, packetId, NF_ACCEPT, netherConfig.markDeny, 0, NULL); - if (verdict == NetherVerdict::allowAndLog) - ret = nfq_set_verdict2 (queueHandle, packetId, NF_ACCEPT, netherConfig.markAllowAndLog, 0, NULL); - - if (ret == -1) - LOGW("can't set verdict for packetId=" << packetId); + int ret = 0; + LOGD("id=" << packetId << " verdict=" << verdictToString(verdict)); + + if(verdict == NetherVerdict::allow) + ret = nfq_set_verdict(queueHandle, packetId, NF_ACCEPT, 0, NULL); + if(verdict == NetherVerdict::deny) + ret = nfq_set_verdict2(queueHandle, packetId, NF_ACCEPT, netherConfig.markDeny, 0, NULL); + if(verdict == NetherVerdict::allowAndLog) + ret = nfq_set_verdict2(queueHandle, packetId, NF_ACCEPT, netherConfig.markAllowAndLog, 0, NULL); + + if(ret == -1) + LOGW("can't set verdict for packetId=" << packetId); } -const bool NetherNetlink::reload() +bool NetherNetlink::reload() { - return (true); + return (true); } diff --git a/src/nether_NetworkUtils.cpp b/src/nether_NetworkUtils.cpp index 8fbe8fa..d2fe3d5 100644 --- a/src/nether_NetworkUtils.cpp +++ b/src/nether_NetworkUtils.cpp @@ -22,8 +22,6 @@ * @brief Network utility functions for nether */ -#include -#include #include "nether_Utils.h" #define IP_PROTOCOL_UDP (0x11) @@ -38,116 +36,116 @@ void decodePacket(NetherPacket &packet, unsigned char *payload) { - uint8_t ipVersion = (payload[0] >> 4) & 0x0F; - - switch(ipVersion) - { - case 4: - packet.protocolType = NetherProtocolType::IPv4; - decodeIPv4Packet(packet, payload); - break; - case 6: - packet.protocolType = NetherProtocolType::IPv6; - decodeIPv6Packet(packet, payload); - break; - default: - packet.transportType = NetherTransportType::unknownTransportType; - packet.protocolType = NetherProtocolType::unknownProtocolType; - break; - } + uint8_t ipVersion = (payload[0] >> 4) & 0x0F; + + switch(ipVersion) + { + case 4: + packet.protocolType = NetherProtocolType::IPv4; + decodeIPv4Packet(packet, payload); + break; + case 6: + packet.protocolType = NetherProtocolType::IPv6; + decodeIPv6Packet(packet, payload); + break; + default: + packet.transportType = NetherTransportType::unknownTransportType; + packet.protocolType = NetherProtocolType::unknownProtocolType; + break; + } } void decodeIPv6Packet(NetherPacket &packet, unsigned char *payload) { - const uint16_t startOfIpPayload = 40; - uint8_t nextProto; - - memcpy(packet.localAddress, &payload[8], NETHER_NETWORK_IPV6_ADDR_LEN); - memcpy(packet.remoteAddress, &payload[24], NETHER_NETWORK_IPV6_ADDR_LEN); - - nextProto = payload[6]; - - switch(nextProto) - { - case IP_PROTOCOL_UDP: - packet.transportType = NetherTransportType::UDP; - decodeUdp(packet, &payload[startOfIpPayload]); - break; - case IP_PROTOCOL_TCP: - packet.transportType = NetherTransportType::TCP; - decodeTcp(packet, &payload[startOfIpPayload]); - break; - case IP_PROTOCOL_ICMP: - packet.transportType = NetherTransportType::ICMP; - break; - case IP_PROTOCOL_IGMP: - packet.transportType = NetherTransportType::IGMP; - break; - default: - packet.transportType = NetherTransportType::unknownTransportType; - break; - } + const uint16_t startOfIpPayload = 40; + uint8_t nextProto; + + memcpy(packet.localAddress, &payload[8], NETHER_NETWORK_IPV6_ADDR_LEN); + memcpy(packet.remoteAddress, &payload[24], NETHER_NETWORK_IPV6_ADDR_LEN); + + nextProto = payload[6]; + + switch(nextProto) + { + case IPPROTO_UDP: + packet.transportType = NetherTransportType::UDP; + decodeUdp(packet, &payload[startOfIpPayload]); + break; + case IPPROTO_TCP: + packet.transportType = NetherTransportType::TCP; + decodeTcp(packet, &payload[startOfIpPayload]); + break; + case IPPROTO_ICMP: + packet.transportType = NetherTransportType::ICMP; + break; + case IPPROTO_IGMP: + packet.transportType = NetherTransportType::IGMP; + break; + default: + packet.transportType = NetherTransportType::unknownTransportType; + break; + } } void decodeIPv4Packet(NetherPacket &packet, unsigned char *payload) { - uint16_t startOfIpPayload = 0; - uint8_t nextProto; - - startOfIpPayload = (payload[0]&0x0F) << 2; - - memcpy(packet.localAddress, &payload[12], NETHER_NETWORK_IPV4_ADDR_LEN); - memcpy(packet.remoteAddress, &payload[16], NETHER_NETWORK_IPV4_ADDR_LEN); - - nextProto = payload[9]; - - switch(nextProto) - { - case IP_PROTOCOL_UDP: - packet.transportType = NetherTransportType::UDP; - decodeUdp(packet, &payload[startOfIpPayload]); - break; - case IP_PROTOCOL_TCP: - packet.transportType = NetherTransportType::TCP; - decodeTcp(packet, &payload[startOfIpPayload]); - break; - case IP_PROTOCOL_ICMP: - packet.transportType = NetherTransportType::ICMP; - break; - case IP_PROTOCOL_IGMP: - packet.transportType = NetherTransportType::IGMP; - default: - packet.transportType = NetherTransportType::unknownTransportType; - break; - } + uint16_t startOfIpPayload = 0; + uint8_t nextProto; + + startOfIpPayload = (payload[0]&0x0F) << 2; + + memcpy(packet.localAddress, &payload[12], NETHER_NETWORK_IPV4_ADDR_LEN); + memcpy(packet.remoteAddress, &payload[16], NETHER_NETWORK_IPV4_ADDR_LEN); + + nextProto = payload[9]; + + switch(nextProto) + { + case IPPROTO_UDP: + packet.transportType = NetherTransportType::UDP; + decodeUdp(packet, &payload[startOfIpPayload]); + break; + case IPPROTO_TCP: + packet.transportType = NetherTransportType::TCP; + decodeTcp(packet, &payload[startOfIpPayload]); + break; + case IPPROTO_ICMP: + packet.transportType = NetherTransportType::ICMP; + break; + case IPPROTO_IGMP: + packet.transportType = NetherTransportType::IGMP; + default: + packet.transportType = NetherTransportType::unknownTransportType; + break; + } } void decodeTcp(NetherPacket &packet, unsigned char *payload) { - packet.localPort = ntohs(*(unsigned short*) &payload[0]); - packet.remotePort = ntohs(*(unsigned short*) &payload[2]); + packet.localPort = ntohs(*(unsigned short*) &payload[0]); + packet.remotePort = ntohs(*(unsigned short*) &payload[2]); } void decodeUdp(NetherPacket &packet, unsigned char *payload) { - packet.localPort = ntohs(*(unsigned short*) &payload[0]); - packet.remotePort = ntohs(*(unsigned short*) &payload[2]); + packet.localPort = ntohs(*(unsigned short*) &payload[0]); + packet.remotePort = ntohs(*(unsigned short*) &payload[2]); } -const std::string ipAddressToString(const char *src, enum NetherProtocolType type) +std::string ipAddressToString(const char *src, enum NetherProtocolType type) { - switch(type) - { - case NetherProtocolType::IPv4: - return (stringFormat("%u.%u.%u.%u", src[0]&0xff,src[1]&0xff,src[2]&0xff,src[3]&0xff)); - case NetherProtocolType::IPv6: - return (stringFormat("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", - ntohs(*(uint16_t*) &src[0]), ntohs(*(uint16_t*) &src[2]), - ntohs(*(uint16_t*) &src[4]), ntohs(*(uint16_t*) &src[6]), - ntohs(*(uint16_t*) &src[8]), ntohs(*(uint16_t*) &src[10]), - ntohs(*(uint16_t*) &src[12]), ntohs(*(uint16_t*) &src[14]))); - default: - return ("(unknown)"); - } + switch(type) + { + case NetherProtocolType::IPv4: + return (stringFormat("%u.%u.%u.%u", src[0]&0xff,src[1]&0xff,src[2]&0xff,src[3]&0xff)); + case NetherProtocolType::IPv6: + return (stringFormat("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", + ntohs(*(uint16_t*) &src[0]), ntohs(*(uint16_t*) &src[2]), + ntohs(*(uint16_t*) &src[4]), ntohs(*(uint16_t*) &src[6]), + ntohs(*(uint16_t*) &src[8]), ntohs(*(uint16_t*) &src[10]), + ntohs(*(uint16_t*) &src[12]), ntohs(*(uint16_t*) &src[14]))); + default: + return ("(unknown)"); + } } -- 2.7.4 From 5743683d0adec7e63e819fa4ac04e6e08985e75e Mon Sep 17 00:00:00 2001 From: RomanKubiak Date: Mon, 3 Aug 2015 15:19:40 +0200 Subject: [PATCH 03/16] Modified sources to eliminate pedantic warnings from gcc. - split function declaration and implementation - delt with unsigned/signed comparison in Cynara backend Change-Id: I1b77af78292915efa9e850d32445c97d5893c513 --- include/nether_CynaraBackend.h | 11 +-- include/nether_FileBackend.h | 23 +----- include/nether_Utils.h | 168 +++------------------------------------- src/nether_CynaraBackend.cpp | 36 +++++---- src/nether_FileBackend.cpp | 23 ++++++ src/nether_NetworkUtils.cpp | 9 +++ src/nether_Utils.cpp | 172 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 241 insertions(+), 201 deletions(-) create mode 100644 src/nether_Utils.cpp diff --git a/include/nether_CynaraBackend.h b/include/nether_CynaraBackend.h index c7f9fff..3825d41 100644 --- a/include/nether_CynaraBackend.h +++ b/include/nether_CynaraBackend.h @@ -33,16 +33,7 @@ #define NETHER_CYNARA_INTERNET_PRIVILEGE "http://tizen.org/privilege/internet" -static const std::string cynaraErrorCodeToString(int cynaraErrorCode) -{ - char errorString[512]; - int ret; - - if((ret = cynara_strerror(cynaraErrorCode, errorString, 512)) == CYNARA_API_SUCCESS) - return (std::string(errorString, strlen(errorString))); - else - return ("Failed to get error string representation, code="+ret); -} +const std::string cynaraErrorCodeToString(int cynaraErrorCode); class NetherManager; diff --git a/include/nether_FileBackend.h b/include/nether_FileBackend.h index 63c8a77..1ab543f 100644 --- a/include/nether_FileBackend.h +++ b/include/nether_FileBackend.h @@ -53,28 +53,7 @@ struct PolicyEntry NetherVerdict verdict; }; -static const std::string dumpPolicyEntry(const PolicyEntry &entry) -{ - std::stringstream stream; - stream << "UID="; - if(entry.uid == NETHER_INVALID_UID) - stream << "*"; - else - stream << entry.uid; - stream << " GID="; - if(entry.gid == NETHER_INVALID_GID) - stream << "*"; - else stream << entry.gid; - stream << " SECCTX="; - if(entry.securityContext.empty()) - stream << "*"; - else - stream << entry.securityContext; - stream << " VERDICT="; - stream << verdictToString(entry.verdict); - - return (stream.str()); -} +const std::string dumpPolicyEntry(const PolicyEntry &entry); class NetherFileBackend : public NetherPolicyBackend { diff --git a/include/nether_Utils.h b/include/nether_Utils.h index 764ce78..2d01abe 100644 --- a/include/nether_Utils.h +++ b/include/nether_Utils.h @@ -19,13 +19,14 @@ /** * @file * @author Roman Kubiak (r.kubiak@samsung.com) - * @brief utility functions + * @brief utility functions declarations */ #ifndef NETHER_UTILS_H #define NETHER_UTILS_H #include "nether_Types.h" + void decodePacket(NetherPacket &packet, unsigned char *payload); void decodeIPv4Packet(NetherPacket &packet, unsigned char *payload); void decodeIPv6Packet(NetherPacket &packet, unsigned char *payload); @@ -33,160 +34,15 @@ void decodeTcp(NetherPacket &packet, unsigned char *payload); void decodeUdp(NetherPacket &packet, unsigned char *payload); std::string ipAddressToString(const char *src, enum NetherProtocolType type); -static NetherVerdict stringToVerdict(char *verdictAsString) -{ - if(verdictAsString) - { - if(strncasecmp(verdictAsString, "allow_log", 9) == 0) - return (NetherVerdict::allowAndLog); - if(strncasecmp(verdictAsString, "allow", 6) == 0) - return (NetherVerdict::allow); - if(strncasecmp(verdictAsString, "deny", 4) == 0) - return (NetherVerdict::deny); - } - return (NetherVerdict::allowAndLog); -} - -static NetherPolicyBackendType stringToBackendType(char *backendAsString) -{ - if(strcasecmp(backendAsString, "cynara") == 0) - return (NetherPolicyBackendType::cynaraBackend); - if(strcasecmp(backendAsString, "file") == 0) - return (NetherPolicyBackendType::fileBackend); - if(strcasecmp(backendAsString, "dummy") == 0) - return (NetherPolicyBackendType::dummyBackend); - - return (NetherPolicyBackendType::dummyBackend); -} - -static NetherLogBackendType stringToLogBackendType(char *backendAsString) -{ - if(strcasecmp(backendAsString, "stderr") == 0) - return (NetherLogBackendType::stderrBackend); - if(strcasecmp(backendAsString, "syslog") == 0) - return (NetherLogBackendType::syslogBackend); - if(strcasecmp(backendAsString, "journal") == 0) - return (NetherLogBackendType::journalBackend); - if(strcasecmp(backendAsString, "file") == 0) - return (NetherLogBackendType::logfileBackend); - if(strcasecmp(backendAsString, "null") == 0) - return (NetherLogBackendType::nullBackend); - - return (NetherLogBackendType::nullBackend); -} - -static std::string logBackendTypeToString(const NetherLogBackendType backendType) -{ - switch(backendType) - { - case NetherLogBackendType::stderrBackend: - return ("stderr"); - case NetherLogBackendType::syslogBackend: - return ("syslog"); - case NetherLogBackendType::journalBackend: - return ("journal"); - case NetherLogBackendType::logfileBackend: - return ("file"); - case NetherLogBackendType::nullBackend: - return ("null"); - } - return ("null"); -} - -static std::string backendTypeToString(const NetherPolicyBackendType backendType) -{ - switch(backendType) - { - case NetherPolicyBackendType::cynaraBackend: - return ("cynara"); - case NetherPolicyBackendType::fileBackend: - return ("file"); - case NetherPolicyBackendType::dummyBackend: - default: - return ("dummy"); - } -} - -static std::string verdictToString(const NetherVerdict verdict) -{ - switch(verdict) - { - case NetherVerdict::allow: - return ("ALLOW"); - case NetherVerdict::allowAndLog: - return ("ALLOW_LOG"); - case NetherVerdict::deny: - return ("DENY"); - case NetherVerdict::noVerdictYet: - return ("NO_VERDICT_YET"); - } - return ("NO_VERDICT_YET"); -} - -static std::string transportToString(const NetherTransportType transportType) -{ - switch(transportType) - { - case NetherTransportType::TCP: - return ("TCP"); - case NetherTransportType::UDP: - return ("UDP"); - case NetherTransportType::ICMP: - return ("ICMP"); - case NetherTransportType::IGMP: - return ("IGMP"); - case NetherTransportType::unknownTransportType: - default: - return ("UNKNOWN"); - } -} - -static std::string protocolToString(const NetherProtocolType protocolType) -{ - switch(protocolType) - { - case NetherProtocolType::IPv4: - return ("IPv4"); - case NetherProtocolType::IPv6: - return ("IPv6"); - default: - return ("UNKNOWN"); - } -} - -static std::string packetToString(const NetherPacket &packet) -{ - std::stringstream stream; - stream << "ID="; - stream << packet.id; - stream << " SECCTX="; - stream << packet.securityContext; - stream << " UID="; - stream << packet.uid; - stream << " GID="; - stream << packet.gid; - stream << " PROTO="; - stream << protocolToString(packet.protocolType); - stream << " TRANSPORT="; - stream << transportToString(packet.transportType); - stream << " SADDR="; - stream << ipAddressToString(&packet.localAddress[0], packet.protocolType); - stream << ":"; - stream << packet.localPort; - stream << " DADDR="; - stream << ipAddressToString(&packet.remoteAddress[0], packet.protocolType); - stream << ":"; - stream << packet.remotePort; - return (stream.str()); -} - -template -std::string stringFormat(const char* format, Args ... args) -{ - size_t size = snprintf(nullptr, 0, format, args ...) + 1; // Extra space for '\0' - std::unique_ptr buf(new char[ size ]); - snprintf(buf.get(), size, format, args ...); - return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside -} +NetherVerdict stringToVerdict(char *verdictAsString); +NetherPolicyBackendType stringToBackendType(char *backendAsString); +NetherLogBackendType stringToLogBackendType(char *backendAsString); +std::string logBackendTypeToString(const NetherLogBackendType backendType); +std::string backendTypeToString(const NetherPolicyBackendType backendType); +std::string verdictToString(const NetherVerdict verdict); +std::string transportToString(const NetherTransportType transportType); +std::string protocolToString(const NetherProtocolType protocolType); +std::string packetToString(const NetherPacket &packet); +template std::string stringFormat(const char* format, Args ... args); #endif // NETHER_UTILS_H diff --git a/src/nether_CynaraBackend.cpp b/src/nether_CynaraBackend.cpp index 67405ae..097d56d 100644 --- a/src/nether_CynaraBackend.cpp +++ b/src/nether_CynaraBackend.cpp @@ -26,6 +26,17 @@ #ifdef HAVE_CYNARA +const std::string cynaraErrorCodeToString(int cynaraErrorCode) +{ + char errorString[512]; + int ret; + + if((ret = cynara_strerror(cynaraErrorCode, errorString, 512)) == CYNARA_API_SUCCESS) + return (std::string(errorString, strlen(errorString))); + else + return ("Failed to get error string representation, code="+ret); +} + NetherCynaraBackend::NetherCynaraBackend(const NetherConfig &netherConfig) : NetherPolicyBackend(netherConfig), currentCynaraDescriptor(0), cynaraLastResult(CYNARA_API_UNKNOWN_ERROR) @@ -77,7 +88,11 @@ bool NetherCynaraBackend::enqueueVerdict(const NetherPacket &packet) { cynara_check_id checkId; - cynaraLastResult = cynara_async_check_cache(cynaraContext, packet.securityContext.c_str(), "", std::to_string(packet.uid).c_str(), NETHER_CYNARA_INTERNET_PRIVILEGE); + cynaraLastResult = cynara_async_check_cache(cynaraContext, + packet.securityContext.c_str(), + "", + std::to_string(packet.uid).c_str(), + NETHER_CYNARA_INTERNET_PRIVILEGE); LOGD("cynara_async_check_cache ctx=" << packet.securityContext.c_str() << " user=" << std::to_string(packet.uid).c_str() << " privilege=" << NETHER_CYNARA_INTERNET_PRIVILEGE); @@ -100,6 +115,7 @@ bool NetherCynaraBackend::enqueueVerdict(const NetherPacket &packet) &checkId, &checkCallback, this); + if(cynaraLastResult == CYNARA_API_SUCCESS) { responseQueue[checkId] = packet.id; @@ -128,20 +144,14 @@ bool NetherCynaraBackend::enqueueVerdict(const NetherPacket &packet) void NetherCynaraBackend::setCynaraVerdict(cynara_check_id checkId, int cynaraResult) { - u_int32_t packetId = 0; - if((packetId = responseQueue[checkId]) >= 0) - { - responseQueue[checkId] = -1; - - if(cynaraResult == CYNARA_API_ACCESS_ALLOWED) - castVerdict(packetId, NetherVerdict::allow); - else - castVerdict(packetId, NetherVerdict::deny); + u_int32_t packetId = responseQueue[checkId]; - return; - } + if(cynaraResult == CYNARA_API_ACCESS_ALLOWED) + castVerdict(packetId, NetherVerdict::allow); + else + castVerdict(packetId, NetherVerdict::deny); - LOGW("checkId=" << checkId << " has no assosiated packetId"); + return; } int NetherCynaraBackend::getDescriptor() diff --git a/src/nether_FileBackend.cpp b/src/nether_FileBackend.cpp index 2a69733..5eab4bd 100644 --- a/src/nether_FileBackend.cpp +++ b/src/nether_FileBackend.cpp @@ -24,6 +24,29 @@ #include "nether_FileBackend.h" +const std::string dumpPolicyEntry(const PolicyEntry &entry) +{ + std::stringstream stream; + stream << "UID="; + if(entry.uid == NETHER_INVALID_UID) + stream << "*"; + else + stream << entry.uid; + stream << " GID="; + if(entry.gid == NETHER_INVALID_GID) + stream << "*"; + else stream << entry.gid; + stream << " SECCTX="; + if(entry.securityContext.empty()) + stream << "*"; + else + stream << entry.securityContext; + stream << " VERDICT="; + stream << verdictToString(entry.verdict); + + return (stream.str()); +} + NetherFileBackend::NetherFileBackend(const NetherConfig &netherConfig) : NetherPolicyBackend(netherConfig) { diff --git a/src/nether_NetworkUtils.cpp b/src/nether_NetworkUtils.cpp index d2fe3d5..f72789f 100644 --- a/src/nether_NetworkUtils.cpp +++ b/src/nether_NetworkUtils.cpp @@ -149,3 +149,12 @@ std::string ipAddressToString(const char *src, enum NetherProtocolType type) return ("(unknown)"); } } + +template +std::string stringFormat(const char* format, Args ... args) +{ + size_t size = snprintf(nullptr, 0, format, args ...) + 1; // Extra space for '\0' + std::unique_ptr buf(new char[ size ]); + snprintf(buf.get(), size, format, args ...); + return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside +} diff --git a/src/nether_Utils.cpp b/src/nether_Utils.cpp new file mode 100644 index 0000000..90460fa --- /dev/null +++ b/src/nether_Utils.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Roman Kubiak (r.kubiak@samsung.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +/** + * @file + * @author Roman Kubiak (r.kubiak@samsung.com) + * @brief utility functions implementation + */ + +#include "nether_Utils.h" + +NetherVerdict stringToVerdict(char *verdictAsString) +{ + if(verdictAsString) + { + if(strncasecmp(verdictAsString, "allow_log", 9) == 0) + return (NetherVerdict::allowAndLog); + if(strncasecmp(verdictAsString, "allow", 6) == 0) + return (NetherVerdict::allow); + if(strncasecmp(verdictAsString, "deny", 4) == 0) + return (NetherVerdict::deny); + } + return (NetherVerdict::allowAndLog); +} + +NetherPolicyBackendType stringToBackendType(char *backendAsString) +{ + if(strcasecmp(backendAsString, "cynara") == 0) + return (NetherPolicyBackendType::cynaraBackend); + if(strcasecmp(backendAsString, "file") == 0) + return (NetherPolicyBackendType::fileBackend); + if(strcasecmp(backendAsString, "dummy") == 0) + return (NetherPolicyBackendType::dummyBackend); + + return (NetherPolicyBackendType::dummyBackend); +} + +NetherLogBackendType stringToLogBackendType(char *backendAsString) +{ + if(strcasecmp(backendAsString, "stderr") == 0) + return (NetherLogBackendType::stderrBackend); + if(strcasecmp(backendAsString, "syslog") == 0) + return (NetherLogBackendType::syslogBackend); + if(strcasecmp(backendAsString, "journal") == 0) + return (NetherLogBackendType::journalBackend); + if(strcasecmp(backendAsString, "file") == 0) + return (NetherLogBackendType::logfileBackend); + if(strcasecmp(backendAsString, "null") == 0) + return (NetherLogBackendType::nullBackend); + + return (NetherLogBackendType::nullBackend); +} + +std::string logBackendTypeToString(const NetherLogBackendType backendType) +{ + switch(backendType) + { + case NetherLogBackendType::stderrBackend: + return ("stderr"); + case NetherLogBackendType::syslogBackend: + return ("syslog"); + case NetherLogBackendType::journalBackend: + return ("journal"); + case NetherLogBackendType::logfileBackend: + return ("file"); + case NetherLogBackendType::nullBackend: + return ("null"); + } + return ("null"); +} + +std::string backendTypeToString(const NetherPolicyBackendType backendType) +{ + switch(backendType) + { + case NetherPolicyBackendType::cynaraBackend: + return ("cynara"); + case NetherPolicyBackendType::fileBackend: + return ("file"); + case NetherPolicyBackendType::dummyBackend: + default: + return ("dummy"); + } +} + +std::string verdictToString(const NetherVerdict verdict) +{ + switch(verdict) + { + case NetherVerdict::allow: + return ("ALLOW"); + case NetherVerdict::allowAndLog: + return ("ALLOW_LOG"); + case NetherVerdict::deny: + return ("DENY"); + case NetherVerdict::noVerdictYet: + return ("NO_VERDICT_YET"); + } + return ("NO_VERDICT_YET"); +} + +std::string transportToString(const NetherTransportType transportType) +{ + switch(transportType) + { + case NetherTransportType::TCP: + return ("TCP"); + case NetherTransportType::UDP: + return ("UDP"); + case NetherTransportType::ICMP: + return ("ICMP"); + case NetherTransportType::IGMP: + return ("IGMP"); + case NetherTransportType::unknownTransportType: + default: + return ("UNKNOWN"); + } +} + +std::string protocolToString(const NetherProtocolType protocolType) +{ + switch(protocolType) + { + case NetherProtocolType::IPv4: + return ("IPv4"); + case NetherProtocolType::IPv6: + return ("IPv6"); + default: + return ("UNKNOWN"); + } +} + +std::string packetToString(const NetherPacket &packet) +{ + std::stringstream stream; + stream << "ID="; + stream << packet.id; + stream << " SECCTX="; + stream << packet.securityContext; + stream << " UID="; + stream << packet.uid; + stream << " GID="; + stream << packet.gid; + stream << " PROTO="; + stream << protocolToString(packet.protocolType); + stream << " TRANSPORT="; + stream << transportToString(packet.transportType); + stream << " SADDR="; + stream << ipAddressToString(&packet.localAddress[0], packet.protocolType); + stream << ":"; + stream << packet.localPort; + stream << " DADDR="; + stream << ipAddressToString(&packet.remoteAddress[0], packet.protocolType); + stream << ":"; + stream << packet.remotePort; + return (stream.str()); +} -- 2.7.4 From 20b569b992b06e61fc2502ac96fc7a92863f871c Mon Sep 17 00:00:00 2001 From: RomanKubiak Date: Tue, 4 Aug 2015 14:04:53 +0200 Subject: [PATCH 04/16] Fixed a compilation error when cynara is not available. Change-Id: Ifa595f3cc1ef31d758cb40f468a46e1a36f8abd7 --- include/nether_Types.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/nether_Types.h b/include/nether_Types.h index 9991a30..146b62b 100644 --- a/include/nether_Types.h +++ b/include/nether_Types.h @@ -68,8 +68,8 @@ #define NETHER_PRIMARY_BACKEND NetherPolicyBackendType::cynaraBackend #define NETHER_BACKUP_BACKEND NetherPolicyBackendType::fileBackend #else -#define NETHER_PRIMARY_BACKEND fileBackend -#define NETHER_BACKUP_BACKEND dummyBackend +#define NETHER_PRIMARY_BACKEND NetherPolicyBackendType::fileBackend +#define NETHER_BACKUP_BACKEND NetherPolicyBackendType::dummyBackend #endif // HAVE_CYNARA #define NETHER_DEFAULT_VERDICT NetherVerdict::allowAndLog -- 2.7.4 From 69cadd81c7a329daf02a987eb02861ab5516bf0c Mon Sep 17 00:00:00 2001 From: RomanKubiak Date: Tue, 4 Aug 2015 14:24:51 +0200 Subject: [PATCH 05/16] Added a fix for malformed policy files. Change-Id: Ia362e8003df4eb3af0ccb2d47482d58d1b3edee9 --- src/nether_FileBackend.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/nether_FileBackend.cpp b/src/nether_FileBackend.cpp index 5eab4bd..c054140 100644 --- a/src/nether_FileBackend.cpp +++ b/src/nether_FileBackend.cpp @@ -107,7 +107,7 @@ bool NetherFileBackend::parsePolicyFile(std::ifstream &policyFile) tokens = split(line, NETHER_POLICY_CREDS_DELIM); - if(tokens.size() > 0) + if(tokens.size() > 0 && tokens.size() > verdictToken) { PolicyEntry entry { tokens[PolicyFileTokens::uidToken].empty() ? NETHER_INVALID_UID : @@ -122,6 +122,10 @@ bool NetherFileBackend::parsePolicyFile(std::ifstream &policyFile) LOGD("\t"< Date: Tue, 4 Aug 2015 14:39:48 +0200 Subject: [PATCH 06/16] Packet copying is now optional. We need to copy packets to userspace to get TCP/IP information (address, port, protocol) This has been made optional now. Change-Id: Ic753a8ecacdf460b2587f65457a80e1da9bb21a6 --- include/nether_Types.h | 77 ++++++++++++++++++++++++++++---------------------- src/CMakeLists.txt | 4 +++ src/nether_Main.cpp | 9 +++++- src/nether_Netlink.cpp | 2 +- 4 files changed, 56 insertions(+), 36 deletions(-) diff --git a/include/nether_Types.h b/include/nether_Types.h index 146b62b..519f21c 100644 --- a/include/nether_Types.h +++ b/include/nether_Types.h @@ -65,33 +65,41 @@ #endif // HAVE_SYSTEMD_JOURNAL #if defined(HAVE_CYNARA) -#define NETHER_PRIMARY_BACKEND NetherPolicyBackendType::cynaraBackend -#define NETHER_BACKUP_BACKEND NetherPolicyBackendType::fileBackend +#define NETHER_PRIMARY_BACKEND NetherPolicyBackendType::cynaraBackend +#define NETHER_BACKUP_BACKEND NetherPolicyBackendType::fileBackend #else -#define NETHER_PRIMARY_BACKEND NetherPolicyBackendType::fileBackend -#define NETHER_BACKUP_BACKEND NetherPolicyBackendType::dummyBackend +#define NETHER_PRIMARY_BACKEND NetherPolicyBackendType::fileBackend +#define NETHER_BACKUP_BACKEND NetherPolicyBackendType::dummyBackend #endif // HAVE_CYNARA -#define NETHER_DEFAULT_VERDICT NetherVerdict::allowAndLog -#define NETHER_PACKET_BUFFER_SIZE 4096 -#define NETHER_INVALID_UID (uid_t) -1 -#define NETHER_INVALID_GID (gid_t) -1 -#define NETHER_NETWORK_ADDR_LEN 16 /* enough to hold ipv4 and ipv6 */ -#define NETHER_NETWORK_IPV4_ADDR_LEN 4 -#define NETHER_NETWORK_IPV6_ADDR_LEN 16 -#define NETHER_MAX_USER_LEN 32 -#define NETLINK_DROP_MARK 3 -#define NETLINK_ALLOWLOG_MARK 4 -#define NETHER_LOG_BACKEND NetherLogBackendType::stderrBackend -#define NETHER_IPTABLES_RESTORE_PATH "/usr/sbin/iptables-restore" +#if defined(COPY_PACKETS) +#define NETLINK_COPY_PACKETS 1 +#else +#define NETLINK_COPY_PACKETS 0 +#endif // COPY_PACKETS + #ifndef NETHER_RULES_PATH -#define NETHER_RULES_PATH "/etc/nether/nether.rules" +#define NETHER_RULES_PATH "/etc/nether/nether.rules" #endif // NETHER_RULES_PATH #ifndef NETHER_POLICY_FILE -#define NETHER_POLICY_FILE "/etc/nether/nether.policy" +#define NETHER_POLICY_FILE "/etc/nether/nether.policy" #endif // NETHER_POLICY_FILE + +#define NETHER_DEFAULT_VERDICT NetherVerdict::allowAndLog +#define NETHER_PACKET_BUFFER_SIZE 4096 +#define NETHER_INVALID_UID (uid_t) -1 +#define NETHER_INVALID_GID (gid_t) -1 +#define NETHER_NETWORK_ADDR_LEN 16 /* enough to hold ipv4 and ipv6 */ +#define NETHER_NETWORK_IPV4_ADDR_LEN 4 +#define NETHER_NETWORK_IPV6_ADDR_LEN 16 +#define NETHER_MAX_USER_LEN 32 +#define NETLINK_DROP_MARK 3 +#define NETLINK_ALLOWLOG_MARK 4 +#define NETHER_LOG_BACKEND NetherLogBackendType::stderrBackend +#define NETHER_IPTABLES_RESTORE_PATH "/usr/sbin/iptables-restore" + enum class NetherPolicyBackendType : std::uint8_t { cynaraBackend, @@ -158,24 +166,25 @@ struct NetherPacket struct NetherConfig { - NetherVerdict defaultVerdict = NETHER_DEFAULT_VERDICT; - NetherPolicyBackendType primaryBackendType = NETHER_PRIMARY_BACKEND; - NetherPolicyBackendType backupBackendType = NETHER_BACKUP_BACKEND; - NetherLogBackendType logBackend = NETHER_LOG_BACKEND; - uint8_t markDeny = NETLINK_DROP_MARK; - uint8_t markAllowAndLog = NETLINK_ALLOWLOG_MARK; - int primaryBackendRetries = 3; - int backupBackendRetries = 3; - int debugMode = 0; - int daemonMode = 0; - int queueNumber = 0; - int enableAudit = 0; - int noRules = 0; - std::string backupBackendArgs = NETHER_POLICY_FILE; + NetherVerdict defaultVerdict = NETHER_DEFAULT_VERDICT; + NetherPolicyBackendType primaryBackendType = NETHER_PRIMARY_BACKEND; + NetherPolicyBackendType backupBackendType = NETHER_BACKUP_BACKEND; + NetherLogBackendType logBackend = NETHER_LOG_BACKEND; + uint8_t markDeny = NETLINK_DROP_MARK; + uint8_t markAllowAndLog = NETLINK_ALLOWLOG_MARK; + int primaryBackendRetries = 3; + int backupBackendRetries = 3; + int debugMode = 0; + int daemonMode = 0; + int queueNumber = 0; + int enableAudit = 0; + int noRules = 0; + int copyPackets = NETLINK_COPY_PACKETS; + std::string backupBackendArgs = NETHER_POLICY_FILE; std::string primaryBackendArgs; std::string logBackendArgs; - std::string rulesPath = NETHER_RULES_PATH; - std::string iptablesRestorePath = NETHER_IPTABLES_RESTORE_PATH; + std::string rulesPath = NETHER_RULES_PATH; + std::string iptablesRestorePath = NETHER_IPTABLES_RESTORE_PATH; }; class NetherVerdictListener diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 54cc564..634c635 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -61,6 +61,10 @@ IF (Boost_FOUND) ADD_DEFINITIONS (-DHAVE_BOOST=1) ENDIF () +IF (COPY_PACKETS) + ADD_DEFINITIONS (-DNETLINK_COPY_PACKETS=1) +ENDIF () + INCLUDE_DIRECTORIES(../include ${CYNARA_INCLUDE_DIRS} ${NETFILTER_INCLUDE_DIRS} diff --git a/src/nether_Main.cpp b/src/nether_Main.cpp index d5883e9..13d29b1 100644 --- a/src/nether_Main.cpp +++ b/src/nether_Main.cpp @@ -42,6 +42,7 @@ int main(int argc, char *argv[]) #endif {"daemon", no_argument, &netherConfig.daemonMode, 0}, {"no-rules", no_argument, &netherConfig.noRules, 0}, + {"copy-packets", no_argument, &netherConfig.copyPackets, 0}, {"log", required_argument, 0, 'l'}, {"log-args", required_argument, 0, 'L'}, {"default-verdict", required_argument, 0, 'V'}, @@ -60,7 +61,7 @@ int main(int argc, char *argv[]) while(1) { - c = getopt_long(argc, argv, ":daxl:L:V:p:P:b:B:q:m:M:a:r:i:h", longOptions, &optionIndex); + c = getopt_long(argc, argv, ":daxcl:L:V:p:P:b:B:q:m:M:a:r:i:h", longOptions, &optionIndex); if(c == -1) break; @@ -73,10 +74,15 @@ int main(int argc, char *argv[]) case 'd': netherConfig.daemonMode = 1; break; + case 'x': netherConfig.noRules = 1; break; + case 'c': + netherConfig.copyPackets = 1; + break; + #if defined(HAVE_AUDIT) case 'a': netherConfig.enableAudit = 1; @@ -218,6 +224,7 @@ void showHelp(char *arg) cout<< "Usage:\t"<< arg << " [OPTIONS]\n\n"; cout<< " -d,--daemon\t\t\t\tRun as daemon in the background (default:no)\n"; cout<< " -x,--no-rules\t\t\t\tDon't load iptables rules on start (default:no)\n"; + cout<< " -c,--copy-packets\t\t\tCopy entire packets, needed to read TCP/IP information (default:no)\n"; cout<< " -l,--log=\t\t\tSet logging backend STDERR,SYSLOG"; #if defined(HAVE_SYSTEMD_JOURNAL) cout << ",JOURNAL\n"; diff --git a/src/nether_Netlink.cpp b/src/nether_Netlink.cpp index c0a9994..1f5084c 100644 --- a/src/nether_Netlink.cpp +++ b/src/nether_Netlink.cpp @@ -68,7 +68,7 @@ bool NetherNetlink::initialize() if(nfq_set_queue_flags(queueHandle, NFQA_CFG_F_SECCTX, NFQA_CFG_F_SECCTX)) LOGI("This kernel version does not allow to retrieve security context"); - if(nfq_set_mode(queueHandle, NFQNL_COPY_META, 0xffff) < 0) + if(nfq_set_mode(queueHandle, netherConfig.copyPackets ? NFQNL_COPY_PACKET : NFQNL_COPY_META, 0xffff) < 0) { LOGE("Can't set packet_copy mode"); nfq_destroy_queue(queueHandle); -- 2.7.4 From 61b1c1b12be57ceff2b5e5155aa6951a6c88060b Mon Sep 17 00:00:00 2001 From: RomanKubiak Date: Mon, 10 Aug 2015 17:23:43 +0200 Subject: [PATCH 07/16] Fix for bad policy install path Change-Id: I90e8e565d8f9efd46c34833a74cf59012163d6b0 --- include/nether_Types.h | 4 ++-- src/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/nether_Types.h b/include/nether_Types.h index 519f21c..d634584 100644 --- a/include/nether_Types.h +++ b/include/nether_Types.h @@ -181,10 +181,10 @@ struct NetherConfig int noRules = 0; int copyPackets = NETLINK_COPY_PACKETS; std::string backupBackendArgs = NETHER_POLICY_FILE; - std::string primaryBackendArgs; - std::string logBackendArgs; std::string rulesPath = NETHER_RULES_PATH; std::string iptablesRestorePath = NETHER_IPTABLES_RESTORE_PATH; + std::string primaryBackendArgs; + std::string logBackendArgs; }; class NetherVerdictListener diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 634c635..94d39ef 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -78,7 +78,7 @@ TARGET_LINK_LIBRARIES (nether ) ADD_DEFINITIONS (-DNETHER_RULES_PATH="${CMAKE_INSTALL_DIR}/etc/nether/nether.rules" - -DNETHER_POLICY_FILE="${CMAKE_INSTALL_DIR}/etc/nether/nether.rules" + -DNETHER_POLICY_FILE="${CMAKE_INSTALL_DIR}/etc/nether/nether.policy" ) INSTALL (TARGETS nether RUNTIME DESTINATION bin) -- 2.7.4 From fcfe63265c11b4f58c4020be0ba24f75fc3110db Mon Sep 17 00:00:00 2001 From: RomanKubiak Date: Thu, 13 Aug 2015 13:06:23 +0200 Subject: [PATCH 08/16] Added optional interface information (output interface only) Small fix for daemon mode. Change-Id: I8fa3974ad54f5fd4b403672ba3a4abe3c8e7c568 --- include/nether_Daemon.h | 15 --------- include/nether_Netlink.h | 2 ++ include/nether_Types.h | 4 +++ src/CMakeLists.txt | 3 +- src/nether_Main.cpp | 86 ++++++++++++++++++++++++++++-------------------- src/nether_Netlink.cpp | 40 ++++++++++++++++++++-- src/nether_Utils.cpp | 2 ++ 7 files changed, 97 insertions(+), 55 deletions(-) diff --git a/include/nether_Daemon.h b/include/nether_Daemon.h index 760fadf..cf6f386 100644 --- a/include/nether_Daemon.h +++ b/include/nether_Daemon.h @@ -73,20 +73,5 @@ bool runAsDaemon() umask(0); - /** Close all open file descriptors */ - for(int x = sysconf(_SC_OPEN_MAX); x>0; x--) - { - close(x); - } - - if(open("/dev/null",O_RDONLY) == -1) - return (false); - - if(open("/dev/null",O_WRONLY) == -1) - return (false); - - if(open("/dev/null",O_RDWR) == -1) - return (false); - return (true); } diff --git a/include/nether_Netlink.h b/include/nether_Netlink.h index 39a1b44..a665be5 100644 --- a/include/nether_Netlink.h +++ b/include/nether_Netlink.h @@ -41,6 +41,8 @@ class NetherNetlink : public NetherPacketProcessor bool processPacket(char *packetBuffer, const int packetReadSize); void setVerdict(const u_int32_t packetId, const NetherVerdict verdict); int getDescriptor(); + const NetherConfig &getNetherConfig(); + void getInterfaceInfo(struct nfq_data *nfa, NetherPacket &netherPacket); protected: NetherPacket *processedPacket; diff --git a/include/nether_Types.h b/include/nether_Types.h index d634584..83e9962 100644 --- a/include/nether_Types.h +++ b/include/nether_Types.h @@ -78,6 +78,8 @@ #define NETLINK_COPY_PACKETS 0 #endif // COPY_PACKETS +#define NETLINK_INTERFACE_INFO 0 + #ifndef NETHER_RULES_PATH #define NETHER_RULES_PATH "/etc/nether/nether.rules" #endif // NETHER_RULES_PATH @@ -162,6 +164,7 @@ struct NetherPacket char remoteAddress[NETHER_NETWORK_ADDR_LEN]; NetherTransportType transportType; NetherProtocolType protocolType; + char outdevName[IFNAMSIZ]; }; struct NetherConfig @@ -180,6 +183,7 @@ struct NetherConfig int enableAudit = 0; int noRules = 0; int copyPackets = NETLINK_COPY_PACKETS; + int interfaceInfo = NETLINK_INTERFACE_INFO; std::string backupBackendArgs = NETHER_POLICY_FILE; std::string rulesPath = NETHER_RULES_PATH; std::string iptablesRestorePath = NETHER_IPTABLES_RESTORE_PATH; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 94d39ef..f4e2920 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -78,7 +78,6 @@ TARGET_LINK_LIBRARIES (nether ) ADD_DEFINITIONS (-DNETHER_RULES_PATH="${CMAKE_INSTALL_DIR}/etc/nether/nether.rules" - -DNETHER_POLICY_FILE="${CMAKE_INSTALL_DIR}/etc/nether/nether.policy" -) + -DNETHER_POLICY_FILE="${CMAKE_INSTALL_DIR}/etc/nether/nether.policy") INSTALL (TARGETS nether RUNTIME DESTINATION bin) diff --git a/src/nether_Main.cpp b/src/nether_Main.cpp index 13d29b1..eca8914 100644 --- a/src/nether_Main.cpp +++ b/src/nether_Main.cpp @@ -38,30 +38,31 @@ int main(int argc, char *argv[]) static struct option longOptions[] = { #if defined(HAVE_AUDIT) - {"enable-audit", no_argument, &netherConfig.enableAudit, 0}, + {"enable-audit", no_argument, &netherConfig.enableAudit, 0}, #endif - {"daemon", no_argument, &netherConfig.daemonMode, 0}, - {"no-rules", no_argument, &netherConfig.noRules, 0}, - {"copy-packets", no_argument, &netherConfig.copyPackets, 0}, - {"log", required_argument, 0, 'l'}, - {"log-args", required_argument, 0, 'L'}, - {"default-verdict", required_argument, 0, 'V'}, - {"primary-backend", required_argument, 0, 'p'}, - {"primary-backend-args", required_argument, 0, 'P'}, - {"backup-backend", required_argument, 0, 'b'}, - {"backup-backend-args", required_argument, 0, 'B'}, - {"queue-num", required_argument, 0, 'q'}, - {"mark-deny", required_argument, 0, 'm'}, - {"mark-allow-log", required_argument, 0, 'M'}, - {"rules-path", required_argument, 0, 'r'}, - {"iptables-restore-path", required_argument, 0, 'i'}, - {"help", no_argument, 0, 'h'}, + {"daemon", no_argument, &netherConfig.daemonMode, 0}, + {"no-rules", no_argument, &netherConfig.noRules, 0}, + {"copy-packets", no_argument, &netherConfig.copyPackets, 0}, + {"interface-info", no_argument, &netherConfig.interfaceInfo, 0}, + {"log", required_argument, 0, 'l'}, + {"log-args", required_argument, 0, 'L'}, + {"default-verdict", required_argument, 0, 'V'}, + {"primary-backend", required_argument, 0, 'p'}, + {"primary-backend-args", required_argument, 0, 'P'}, + {"backup-backend", required_argument, 0, 'b'}, + {"backup-backend-args", required_argument, 0, 'B'}, + {"queue-num", required_argument, 0, 'q'}, + {"mark-deny", required_argument, 0, 'm'}, + {"mark-allow-log", required_argument, 0, 'M'}, + {"rules-path", required_argument, 0, 'r'}, + {"iptables-restore-path", required_argument, 0, 'i'}, + {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; while(1) { - c = getopt_long(argc, argv, ":daxcl:L:V:p:P:b:B:q:m:M:a:r:i:h", longOptions, &optionIndex); + c = getopt_long(argc, argv, ":daxcIl:L:V:p:P:b:B:q:m:M:a:r:i:h", longOptions, &optionIndex); if(c == -1) break; @@ -83,6 +84,10 @@ int main(int argc, char *argv[]) netherConfig.copyPackets = 1; break; + case 'I': + netherConfig.interfaceInfo = 1; + break; + #if defined(HAVE_AUDIT) case 'a': netherConfig.enableAudit = 1; @@ -181,21 +186,23 @@ int main(int argc, char *argv[]) #if defined(_DEBUG) << " debug" #endif - << " daemon=" << netherConfig.daemonMode - << " queue=" << netherConfig.queueNumber); - LOGD("primary-backend=" << backendTypeToString(netherConfig.primaryBackendType) - << " primary-backend-args=" << netherConfig.primaryBackendArgs); - LOGD("backup-backend=" << backendTypeToString(netherConfig.backupBackendType) - << " backup-backend-args=" << netherConfig.backupBackendArgs); - LOGD("default-verdict=" << verdictToString(netherConfig.defaultVerdict) - << " mark-deny=" << (int)netherConfig.markDeny - << " mark-allow-log=" << (int)netherConfig.markAllowAndLog); - LOGD("log-backend=" << logBackendTypeToString(netherConfig.logBackend) - << " log-backend-args=" << netherConfig.logBackendArgs); - LOGD("enable-audit=" << (netherConfig.enableAudit ? "yes" : "no") - << " rules-path=" << netherConfig.rulesPath); - LOGD("no-rules=" << (netherConfig.noRules ? "yes" : "no") - << " iptables-restore-path=" << netherConfig.iptablesRestorePath); + << " daemon=" << netherConfig.daemonMode + << " queue=" << netherConfig.queueNumber); + LOGD("primary-backend=" << backendTypeToString(netherConfig.primaryBackendType) + << " primary-backend-args=" << netherConfig.primaryBackendArgs); + LOGD("backup-backend=" << backendTypeToString(netherConfig.backupBackendType) + << " backup-backend-args=" << netherConfig.backupBackendArgs); + LOGD("default-verdict=" << verdictToString(netherConfig.defaultVerdict) + << " mark-deny=" << (int)netherConfig.markDeny + << " mark-allow-log=" << (int)netherConfig.markAllowAndLog); + LOGD("log-backend=" << logBackendTypeToString(netherConfig.logBackend) + << " log-backend-args=" << netherConfig.logBackendArgs); + LOGD("enable-audit=" << (netherConfig.enableAudit ? "yes" : "no") + << " rules-path=" << netherConfig.rulesPath); + LOGD("no-rules=" << (netherConfig.noRules ? "yes" : "no") + << " iptables-restore-path=" << netherConfig.iptablesRestorePath); + LOGD("interface-info=" << (netherConfig.interfaceInfo ? "yes" : "no") + << " copy-packets=" << (netherConfig.copyPackets ? "yes" : "no")); NetherManager manager(netherConfig); @@ -207,14 +214,22 @@ int main(int argc, char *argv[]) if(netherConfig.daemonMode) { + LOGD("FORKING TO BACKGROUND"); if(!runAsDaemon()) { LOGE("Failed to run as daemon: " << strerror(errno)); exit(1); } + else + { + manager.process(); + } + } + else + { + LOGD("RUNNING IF FOREGROUND"); + manager.process(); } - - manager.process(); return (0); } @@ -225,6 +240,7 @@ void showHelp(char *arg) cout<< " -d,--daemon\t\t\t\tRun as daemon in the background (default:no)\n"; cout<< " -x,--no-rules\t\t\t\tDon't load iptables rules on start (default:no)\n"; cout<< " -c,--copy-packets\t\t\tCopy entire packets, needed to read TCP/IP information (default:no)\n"; + cout<< " -I,--interface-info\t\t\tGet interface info for every packet (default:no)\n"; cout<< " -l,--log=\t\t\tSet logging backend STDERR,SYSLOG"; #if defined(HAVE_SYSTEMD_JOURNAL) cout << ",JOURNAL\n"; diff --git a/src/nether_Netlink.cpp b/src/nether_Netlink.cpp index 1f5084c..08af86f 100644 --- a/src/nether_Netlink.cpp +++ b/src/nether_Netlink.cpp @@ -82,9 +82,15 @@ bool NetherNetlink::initialize() return (false); } - nlif = nlif_open(); - if(!nlif) - LOGI("Failed to initialize NLIF subsystem, interface information won't be available"); + if (netherConfig.interfaceInfo) + { + nlif = nlif_open(); + + if(!nlif) + LOGI("Failed to initialize NLIF subsystem, interface information won't be available"); + else + nlif_query(nlif); + } return (true); } @@ -109,6 +115,26 @@ bool NetherNetlink::processPacket(char *packetBuffer, const int packetReadSize) return (true); } +void NetherNetlink::getInterfaceInfo(struct nfq_data *nfa, NetherPacket &netherPacket) +{ + if (netherConfig.interfaceInfo) + { + uint32_t ifi; + + ifi = nfq_get_outdev(nfa); + + if (ifi) + { + nfq_get_outdev_name(nlif, nfa, netherPacket.outdevName); + } + else + { + strncpy(netherPacket.outdevName, "(unknown)", IFNAMSIZ); + netherPacket.outdevName[IFNAMSIZ-1] = '\0'; + } + } +} + int NetherNetlink::callback(struct nfq_q_handle *, struct nfgenmsg *, struct nfq_data *nfa, void *data) { NetherNetlink *me = static_cast(data); @@ -128,6 +154,9 @@ int NetherNetlink::callback(struct nfq_q_handle *, struct nfgenmsg *, struct nfq return (1); } + /* get interface information if requested */ + me->getInterfaceInfo(nfa, packet); + if(nfq_get_uid(nfa, &packet.uid) == 0) LOGW("Failed to get uid for packet id=" << packet.id); @@ -168,3 +197,8 @@ bool NetherNetlink::reload() { return (true); } + +const NetherConfig &NetherNetlink::getNetherConfig() +{ + return (netherConfig); +} diff --git a/src/nether_Utils.cpp b/src/nether_Utils.cpp index 90460fa..29554e0 100644 --- a/src/nether_Utils.cpp +++ b/src/nether_Utils.cpp @@ -152,6 +152,8 @@ std::string packetToString(const NetherPacket &packet) stream << packet.id; stream << " SECCTX="; stream << packet.securityContext; + stream << " OUTDEV="; + stream << packet.outdevName; stream << " UID="; stream << packet.uid; stream << " GID="; -- 2.7.4 From f9413d992a3311d13a03b03c2a070935262237d3 Mon Sep 17 00:00:00 2001 From: RomanKubiak Date: Thu, 13 Aug 2015 16:26:05 +0200 Subject: [PATCH 09/16] Fixed cynara socket initialization. Change-Id: I38fe7751f087a719657e9d6a6da58cea3bf4a9d4 --- src/nether_CynaraBackend.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nether_CynaraBackend.cpp b/src/nether_CynaraBackend.cpp index 097d56d..f28222c 100644 --- a/src/nether_CynaraBackend.cpp +++ b/src/nether_CynaraBackend.cpp @@ -38,7 +38,7 @@ const std::string cynaraErrorCodeToString(int cynaraErrorCode) } NetherCynaraBackend::NetherCynaraBackend(const NetherConfig &netherConfig) - : NetherPolicyBackend(netherConfig), currentCynaraDescriptor(0), + : NetherPolicyBackend(netherConfig), currentCynaraDescriptor(-1), cynaraLastResult(CYNARA_API_UNKNOWN_ERROR) { responseQueue.reserve(1024); -- 2.7.4 From c2dd18e1d1c47ce8a87466416e0b97a4205f5bd9 Mon Sep 17 00:00:00 2001 From: RomanKubiak Date: Thu, 20 Aug 2015 13:31:02 +0200 Subject: [PATCH 10/16] Added a relaxed mode. This allows to run nether in a permissive/relaxed mode where all DENY requestes are actualy allowed but logged via AUDIT. Change-Id: I0f67f061b2697a80d610d1988b706bd92de05944 --- include/nether_Types.h | 4 +++- src/nether_Main.cpp | 11 +++++++++-- src/nether_Netlink.cpp | 10 +++++++++- src/nether_Utils.cpp | 4 ++-- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/include/nether_Types.h b/include/nether_Types.h index 83e9962..a862da4 100644 --- a/include/nether_Types.h +++ b/include/nether_Types.h @@ -99,6 +99,7 @@ #define NETHER_MAX_USER_LEN 32 #define NETLINK_DROP_MARK 3 #define NETLINK_ALLOWLOG_MARK 4 +#define NETLINK_QUEUE_NUM 0 #define NETHER_LOG_BACKEND NetherLogBackendType::stderrBackend #define NETHER_IPTABLES_RESTORE_PATH "/usr/sbin/iptables-restore" @@ -179,10 +180,11 @@ struct NetherConfig int backupBackendRetries = 3; int debugMode = 0; int daemonMode = 0; - int queueNumber = 0; + int queueNumber = NETLINK_QUEUE_NUM; int enableAudit = 0; int noRules = 0; int copyPackets = NETLINK_COPY_PACKETS; + int relaxed = 0; int interfaceInfo = NETLINK_INTERFACE_INFO; std::string backupBackendArgs = NETHER_POLICY_FILE; std::string rulesPath = NETHER_RULES_PATH; diff --git a/src/nether_Main.cpp b/src/nether_Main.cpp index eca8914..1ab5820 100644 --- a/src/nether_Main.cpp +++ b/src/nether_Main.cpp @@ -44,6 +44,7 @@ int main(int argc, char *argv[]) {"no-rules", no_argument, &netherConfig.noRules, 0}, {"copy-packets", no_argument, &netherConfig.copyPackets, 0}, {"interface-info", no_argument, &netherConfig.interfaceInfo, 0}, + {"relaxed", no_argument, &netherConfig.relaxed, 0}, {"log", required_argument, 0, 'l'}, {"log-args", required_argument, 0, 'L'}, {"default-verdict", required_argument, 0, 'V'}, @@ -62,7 +63,7 @@ int main(int argc, char *argv[]) while(1) { - c = getopt_long(argc, argv, ":daxcIl:L:V:p:P:b:B:q:m:M:a:r:i:h", longOptions, &optionIndex); + c = getopt_long(argc, argv, ":daxcIRl:L:V:p:P:b:B:q:m:M:a:r:i:h", longOptions, &optionIndex); if(c == -1) break; @@ -93,6 +94,10 @@ int main(int argc, char *argv[]) netherConfig.enableAudit = 1; break; #endif + case 'R': + netherConfig.relaxed = 1; + break; + case 'l': netherConfig.logBackend = stringToLogBackendType(optarg); break; @@ -203,6 +208,7 @@ int main(int argc, char *argv[]) << " iptables-restore-path=" << netherConfig.iptablesRestorePath); LOGD("interface-info=" << (netherConfig.interfaceInfo ? "yes" : "no") << " copy-packets=" << (netherConfig.copyPackets ? "yes" : "no")); + LOGD("relaxed=" << (netherConfig.relaxed ? "yes" : "no")); NetherManager manager(netherConfig); @@ -241,6 +247,7 @@ void showHelp(char *arg) cout<< " -x,--no-rules\t\t\t\tDon't load iptables rules on start (default:no)\n"; cout<< " -c,--copy-packets\t\t\tCopy entire packets, needed to read TCP/IP information (default:no)\n"; cout<< " -I,--interface-info\t\t\tGet interface info for every packet (default:no)\n"; + cout<< " -R,--relaxed\t\t\t\tRun in relaxed mode, instrad of deny do ACCEPT_LOG(default:no)\n"; cout<< " -l,--log=\t\t\tSet logging backend STDERR,SYSLOG"; #if defined(HAVE_SYSTEMD_JOURNAL) cout << ",JOURNAL\n"; @@ -260,7 +267,7 @@ void showHelp(char *arg) #endif cout<< ",FILE,NONE (defualt:"<< backendTypeToString(NETHER_BACKUP_BACKEND)<< ")\n"; cout<< " -B,--backup-backend-args=\tBackup policy backend arguments (default:" << NETHER_POLICY_FILE << ")\n"; - cout<< " -q,--queue-num=\t\tNFQUEUE queue number to use for receiving packets\n"; + cout<< " -q,--queue-num=\t\tNFQUEUE queue number to use for receiving packets (default:" << NETLINK_QUEUE_NUM << ")\n"; cout<< " -m,--mark-deny=\t\t\tPacket mark to use for DENY verdicts (default:"<< NETLINK_DROP_MARK << ")\n"; cout<< " -M,--mark-allow-log=\t\tPacket mark to use for ALLOW_LOG verdicts (default:" << NETLINK_ALLOWLOG_MARK << ")\n"; #if defined(HAVE_AUDIT) diff --git a/src/nether_Netlink.cpp b/src/nether_Netlink.cpp index 08af86f..bb91510 100644 --- a/src/nether_Netlink.cpp +++ b/src/nether_Netlink.cpp @@ -184,8 +184,16 @@ void NetherNetlink::setVerdict(const u_int32_t packetId, const NetherVerdict ver if(verdict == NetherVerdict::allow) ret = nfq_set_verdict(queueHandle, packetId, NF_ACCEPT, 0, NULL); + if(verdict == NetherVerdict::deny) - ret = nfq_set_verdict2(queueHandle, packetId, NF_ACCEPT, netherConfig.markDeny, 0, NULL); + ret = nfq_set_verdict2(queueHandle, + packetId, + NF_ACCEPT, + /* if we're relaxed, let's not stress out */ + netherConfig.relaxed ? netherConfig.markAllowAndLog : netherConfig.markDeny, + 0, + NULL); + if(verdict == NetherVerdict::allowAndLog) ret = nfq_set_verdict2(queueHandle, packetId, NF_ACCEPT, netherConfig.markAllowAndLog, 0, NULL); diff --git a/src/nether_Utils.cpp b/src/nether_Utils.cpp index 29554e0..2d231eb 100644 --- a/src/nether_Utils.cpp +++ b/src/nether_Utils.cpp @@ -128,7 +128,7 @@ std::string transportToString(const NetherTransportType transportType) return ("IGMP"); case NetherTransportType::unknownTransportType: default: - return ("UNKNOWN"); + return ("(unknown)"); } } @@ -141,7 +141,7 @@ std::string protocolToString(const NetherProtocolType protocolType) case NetherProtocolType::IPv6: return ("IPv6"); default: - return ("UNKNOWN"); + return ("(unknown)"); } } -- 2.7.4 From 325cb774fe9e1db3d8035e4e71d1664219628e17 Mon Sep 17 00:00:00 2001 From: "r.kubiak" Date: Wed, 7 Oct 2015 17:39:19 +0200 Subject: [PATCH 11/16] Cynaara backend init, needs to return a valid descriptor otherwise an error will be reported. Change-Id: I3ea749bd39b7a61cb05d00a8d2cb63c51336cebb --- src/nether_CynaraBackend.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nether_CynaraBackend.cpp b/src/nether_CynaraBackend.cpp index f28222c..097d56d 100644 --- a/src/nether_CynaraBackend.cpp +++ b/src/nether_CynaraBackend.cpp @@ -38,7 +38,7 @@ const std::string cynaraErrorCodeToString(int cynaraErrorCode) } NetherCynaraBackend::NetherCynaraBackend(const NetherConfig &netherConfig) - : NetherPolicyBackend(netherConfig), currentCynaraDescriptor(-1), + : NetherPolicyBackend(netherConfig), currentCynaraDescriptor(0), cynaraLastResult(CYNARA_API_UNKNOWN_ERROR) { responseQueue.reserve(1024); -- 2.7.4 From f94e8a60845215d3a5a1ed68a2be196691c03a06 Mon Sep 17 00:00:00 2001 From: "r.kubiak" Date: Wed, 7 Oct 2015 17:40:26 +0200 Subject: [PATCH 12/16] Added loopback rules, so that the REJECT target can transmit ICMP packets to the process. Change-Id: Idb5494f72e380164ab1473d18ef1f41a83e03ebe --- conf/nether.rules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/nether.rules b/conf/nether.rules index b342507..b7ce458 100644 --- a/conf/nether.rules +++ b/conf/nether.rules @@ -23,9 +23,8 @@ :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [816152:74580343] :POSTROUTING ACCEPT [824147:75308906] +-A OUTPUT -o lo -j ACCEPT -A OUTPUT -p tcp -m state --state NEW -j NFQUEUE --queue-num 0 --queue-bypass -#-A OUTPUT -p udp -j NFQUEUE --queue-num 0 --queue-bypass --A OUTPUT -p icmp -j NFQUEUE --queue-num 0 --queue-bypass COMMIT *filter :INPUT ACCEPT [927054:2081201095] @@ -33,6 +32,7 @@ COMMIT :OUTPUT ACCEPT [805408:74228055] :NETHER-ALLOWLOG - [0:0] :NETHER-DENY - [0:0] +-A OUTPUT -o lo -j ACCEPT -A OUTPUT -m mark --mark 0x3 -j NETHER-DENY -A OUTPUT -m mark --mark 0x4 -j NETHER-ALLOWLOG -A NETHER-ALLOWLOG -j AUDIT --type accept -- 2.7.4 From e83dcf9d12eda50888b6a19ba9a78f8fce3a8946 Mon Sep 17 00:00:00 2001 From: "r.kubiak" Date: Thu, 8 Oct 2015 15:32:24 +0200 Subject: [PATCH 13/16] Added a cynara backend option (passed as a primary backend option -P) cache-size, to control the client side of cynara caache (default is 1000). This size is in cynara objects not kilo-mega/bytes. Change-Id: Ia02053990d01d37a00f8d78ab743d60a7a0e758b --- include/nether_CynaraBackend.h | 3 +++ include/nether_Types.h | 1 + include/nether_Utils.h | 2 +- src/nether_CynaraBackend.cpp | 45 ++++++++++++++++++++++++++++++++++++++++-- src/nether_Utils.cpp | 17 ++++++++++++++++ 5 files changed, 65 insertions(+), 3 deletions(-) diff --git a/include/nether_CynaraBackend.h b/include/nether_CynaraBackend.h index 3825d41..4dd52b1 100644 --- a/include/nether_CynaraBackend.h +++ b/include/nether_CynaraBackend.h @@ -53,9 +53,12 @@ class NetherCynaraBackend : public NetherPolicyBackend static void checkCallback(cynara_check_id check_id, cynara_async_call_cause cause, int response, void *data); private: + void parseBackendArgs(); + void setCacheSize(const size_t newCacheSize); cynara_async *cynaraContext; NetherDescriptorStatus currentCynaraDescriptorStatus; int currentCynaraDescriptor; + cynara_async_configuration *cynaraConfig; std::vector responseQueue; int cynaraLastResult; }; diff --git a/include/nether_Types.h b/include/nether_Types.h index a862da4..57cae36 100644 --- a/include/nether_Types.h +++ b/include/nether_Types.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include diff --git a/include/nether_Utils.h b/include/nether_Utils.h index 2d01abe..146acce 100644 --- a/include/nether_Utils.h +++ b/include/nether_Utils.h @@ -44,5 +44,5 @@ std::string transportToString(const NetherTransportType transportType); std::string protocolToString(const NetherProtocolType protocolType); std::string packetToString(const NetherPacket &packet); template std::string stringFormat(const char* format, Args ... args); - +std::vector tokenize(const std::string &str, const std::string &delimiters); #endif // NETHER_UTILS_H diff --git a/src/nether_CynaraBackend.cpp b/src/nether_CynaraBackend.cpp index 097d56d..224b0e8 100644 --- a/src/nether_CynaraBackend.cpp +++ b/src/nether_CynaraBackend.cpp @@ -23,6 +23,9 @@ */ #include "nether_CynaraBackend.h" +#include "nether_Utils.h" + +using namespace std; #ifdef HAVE_CYNARA @@ -39,18 +42,23 @@ const std::string cynaraErrorCodeToString(int cynaraErrorCode) NetherCynaraBackend::NetherCynaraBackend(const NetherConfig &netherConfig) : NetherPolicyBackend(netherConfig), currentCynaraDescriptor(0), - cynaraLastResult(CYNARA_API_UNKNOWN_ERROR) + cynaraLastResult(CYNARA_API_UNKNOWN_ERROR), cynaraConfig(nullptr) { responseQueue.reserve(1024); + if (netherConfig.primaryBackendArgs.length() != 0) + { + parseBackendArgs(); + } } NetherCynaraBackend::~NetherCynaraBackend() { + cynara_async_configuration_destroy(cynaraConfig); } bool NetherCynaraBackend::initialize() { - cynaraLastResult = cynara_async_initialize(&cynaraContext, NULL, &statusCallback, this); + cynaraLastResult = cynara_async_initialize(&cynaraContext, cynaraConfig, &statusCallback, this); if(cynaraLastResult != CYNARA_API_SUCCESS) { LOGE("Failed to initialize cynara client " << cynaraErrorCodeToString(cynaraLastResult)); @@ -180,4 +188,37 @@ bool NetherCynaraBackend::processEvents() LOGW("cynara_async_process failed " << cynaraErrorCodeToString(ret)); return (false); } + +void NetherCynaraBackend::setCacheSize(const size_t newCacheSize) +{ + int ret; + + if ((ret = cynara_async_configuration_create (&cynaraConfig)) != CYNARA_API_SUCCESS) + { + LOGE("cynara_async_configuration_create failed: " << cynaraErrorCodeToString(ret)); + } + + if ((ret = cynara_async_configuration_set_cache_size(cynaraConfig, newCacheSize)) != CYNARA_API_SUCCESS) + { + LOGE("cynara_async_configuration_set_cache_size failed: " << cynaraErrorCodeToString(ret)); + } + + LOGD("new cache size: " << newCacheSize); +} + +void NetherCynaraBackend::parseBackendArgs() +{ + vector valueNamePairs = tokenize(netherConfig.primaryBackendArgs,";"); + + for (vector::iterator it = valueNamePairs.begin(); it != valueNamePairs.end(); ++it) + { + vector valueNamePair = tokenize(*it, "="); + + if (valueNamePair[0] == "cache-size") + { + std::string::size_type sz; + setCacheSize (stoi (valueNamePair[1], &sz, 10)); + } + } +} #endif diff --git a/src/nether_Utils.cpp b/src/nether_Utils.cpp index 2d231eb..7726dd6 100644 --- a/src/nether_Utils.cpp +++ b/src/nether_Utils.cpp @@ -172,3 +172,20 @@ std::string packetToString(const NetherPacket &packet) stream << packet.remotePort; return (stream.str()); } + +// http://stackoverflow.com/questions/236129/split-a-string-in-c +std::vector tokenize(const std::string &str, const std::string &delimiters) +{ + std::vector v; + typename std::string::size_type start = 0; + auto pos = str.find_first_of(delimiters, start); + while(pos != std::string::npos) { + if(pos != start) // ignore empty tokens + v.emplace_back(str, start, pos - start); + start = pos + 1; + pos = str.find_first_of(delimiters, start); + } + if(start < str.length()) // ignore trailing delimiter + v.emplace_back(str, start, str.length() - start); // add what's left of the string + return v; +} -- 2.7.4 From 998a16ad189481ec9462d0b5550e65cec0c34f09 Mon Sep 17 00:00:00 2001 From: "r.kubiak" Date: Thu, 8 Oct 2015 16:22:55 +0200 Subject: [PATCH 14/16] Added performance test scripts and programs Change-Id: Iaf497786d993e98e6020290e0c5cb33af1461e23 --- tests/Makefile | 4 ++ tests/gen_cynara.sh | 10 +++ tests/gen_labels.sh | 10 +++ tests/gen_rules.sh | 10 +++ tests/load_cynara.sh | 13 ++++ tests/load_rules.sh | 9 +++ tests/smack_net_test.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 218 insertions(+) create mode 100644 tests/Makefile create mode 100755 tests/gen_cynara.sh create mode 100755 tests/gen_labels.sh create mode 100755 tests/gen_rules.sh create mode 100755 tests/load_cynara.sh create mode 100755 tests/load_rules.sh create mode 100644 tests/smack_net_test.c diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000..102df9c --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,4 @@ +all: + gcc -Og smack_net_test.c -o smack_net_test + + \ No newline at end of file diff --git a/tests/gen_cynara.sh b/tests/gen_cynara.sh new file mode 100755 index 0000000..c44e0b6 --- /dev/null +++ b/tests/gen_cynara.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +if [ "$1" == "" ]; then + echo "$0 " + exit 1 +fi + +for i in `cat $1`; do + echo "MANIFESTS;$i;0;http://tizen.org/privilege/internet;65535;" +done diff --git a/tests/gen_labels.sh b/tests/gen_labels.sh new file mode 100755 index 0000000..cbb23e9 --- /dev/null +++ b/tests/gen_labels.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +if [ "$1" == "" ]; then + echo "$0 " + exit 1 +fi + +for i in `seq 0 $1`; do + echo "AppLabel$i" +done diff --git a/tests/gen_rules.sh b/tests/gen_rules.sh new file mode 100755 index 0000000..6d57e1b --- /dev/null +++ b/tests/gen_rules.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +if [ "$1" == "" ]; then + echo "$0 " + exit 1 +fi + +for i in `cat $1`; do + cat rules_template.txt | sed 's/APP_ID/'$i'/g' +done \ No newline at end of file diff --git a/tests/load_cynara.sh b/tests/load_cynara.sh new file mode 100755 index 0000000..875af31 --- /dev/null +++ b/tests/load_cynara.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +if [ "$1" == "" ] || [ "$2" == "" ]; then + echo "$0 " + exit 1 +fi + +for i in `cat $1`; do + echo "remove $i" + cyad -e $2 -r no -c $i -u 0 -p http://tizen.org/privilege/internet + echo "add $1" + cyad -s $2 -c $i -u 0 -p http://tizen.org/privilege/internet -t allow +done diff --git a/tests/load_rules.sh b/tests/load_rules.sh new file mode 100755 index 0000000..adbdce6 --- /dev/null +++ b/tests/load_rules.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +if [ "$1" == "" ]; then + echo "$0 " + exit 1 +fi + +echo "Loading rules" +cat $1 | grep --line-buffered "" > /sys/fs/smackfs/load2 diff --git a/tests/smack_net_test.c b/tests/smack_net_test.c new file mode 100644 index 0000000..b4b691e --- /dev/null +++ b/tests/smack_net_test.c @@ -0,0 +1,162 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_SAMPLES 100000 +#define MAX_LABELS 10000 +#define MAX_LABEL 255 + +char labels[MAX_LABELS][MAX_LABEL]; + +int change_label(const int n) +{ + FILE *fp = fopen ("/proc/self/attr/current", "w"); + + if (fp == NULL) + { + perror("/proc/self/attr/current"); + return (1); + } + + if (fwrite (labels[n], strlen(labels[n]), 1, fp) == 0) + { + perror("/proc/self/attr/current"); + fclose(fp); + return (1); + } + + fclose (fp); + return (0); +} + +int read_labels(const char *labels_file) +{ + FILE *fp = fopen(labels_file, "r"); + int nl = 0; + + if (fp == NULL) + { + perror(labels_file); + return (1); + } + + while (!feof(fp)) + { + if (fgets(labels[nl++], MAX_LABEL, fp) == NULL) + { + printf ("Read %d labels\n", nl); + break; + } + } + + fclose(fp); + return (0); +} + +int con(const char *ip, const int n) +{ + int sockfd = 0; + struct sockaddr_in serv_addr; + + if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + perror("socket"); + return 1; + } + + memset(&serv_addr, '0', sizeof(serv_addr)); + + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(80); + + if(inet_pton(AF_INET, ip, &serv_addr.sin_addr) <= 0) + { + perror("inet_pton"); + return 1; + } + + if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) + { + perror ("connect"); + return 1; + } + + close (sockfd); + + return (0); +} + +int main(int argc, char *argv[]) +{ + int n = 0, conn_all = 0, avg_n = 0; + long avg_every = 0; + long avg_samples[MAX_SAMPLES] = {0}; + long elapsed_samples[MAX_SAMPLES] = {0}; + unsigned long avg_accumulator = 0; + struct timespec tp_start, tp_end; + + if(argc != 5) + { + printf("Usage: %s \n", argv[0]); + return (1); + } + + if (read_labels(argv[4])) + { + printf("Can't read labels %s\n", argv[4]); + return (1); + } + + conn_all = atol(argv[2]); + avg_every = atol(argv[3]); + + for (n = 0; n < conn_all; n++) + { + if (change_label(n)) + { + printf ("change_label failed\n"); + return (1); + } + + clock_gettime (CLOCK_REALTIME, &tp_start); + + if (con(argv[1], n)) + { + printf ("con() failed\n"); + return (1); + } + + clock_gettime (CLOCK_REALTIME, &tp_end); + + elapsed_samples[n] = tp_end.tv_nsec - tp_start.tv_nsec; + avg_accumulator += elapsed_samples[n]; + + if (avg_n++ == avg_every) + { + avg_n = 0; + avg_samples[n] = avg_accumulator / avg_every; + + if (avg_samples[n] < 0) + { + printf ("Bad avg: start:%u end:%u diff:%u accumulator:%u div:%u\n", tp_start.tv_nsec, tp_end.tv_nsec, tp_end.tv_nsec - tp_start.tv_nsec, avg_accumulator, avg_accumulator / avg_every); + } + avg_accumulator = 0; + + + + printf ("Average over %d samples %.4f ms\n", avg_every, avg_samples[n]/1000000.0f); + } + + + } + + return (0); +} -- 2.7.4 From 053c7dd27d362c11f9bc5e9eadef00dda493edaa Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Wed, 18 Nov 2015 15:34:32 +0100 Subject: [PATCH 15/16] Fix potential failures with inheritance Classes being inherited should generally have virtual destructors. There was no problem at the moment, but it will help preventing failures in the future. Change-Id: I5ddd7c6bf5f8bd4751082244bc3730bc3d78691c --- include/nether_Types.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/nether_Types.h b/include/nether_Types.h index 57cae36..84bc99b 100644 --- a/include/nether_Types.h +++ b/include/nether_Types.h @@ -197,6 +197,7 @@ struct NetherConfig class NetherVerdictListener { public: + virtual ~NetherVerdictListener() = default; virtual bool verdictCast(const u_int32_t packetId, const NetherVerdict verdict) = 0; }; @@ -232,6 +233,7 @@ class NetherVerdictCaster class NetherProcessedPacketListener { public: + virtual ~NetherProcessedPacketListener() = default; virtual void packetReceived(const NetherPacket &packet) = 0; }; -- 2.7.4 From cf7877f251c2d6bad1b541aeb3de39ae89b74960 Mon Sep 17 00:00:00 2001 From: "r.kubiak" Date: Thu, 19 Nov 2015 13:48:26 +0100 Subject: [PATCH 16/16] Added apache LICENSE file Change-Id: If9ab9b33a53e93121cfbbe227d2f9b77845a69da --- LICENSE | 203 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..247c97d --- /dev/null +++ b/LICENSE @@ -0,0 +1,203 @@ +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. -- 2.7.4