From 285473ef6cb9249844e31377bb1c71ce3ee2a655 Mon Sep 17 00:00:00 2001 From: RomanKubiak Date: Thu, 16 Jul 2015 16:54:22 +0200 Subject: [PATCH 2/9] Initial source code for nether 0.0.1 (source code only) Change-Id: I16970c3dedd9071c970523a478fbf35e009d13ef --- include/nether_CynaraBackend.h | 50 ++++++++ include/nether_DummyBackend.h | 35 ++++++ include/nether_FileBackend.h | 63 ++++++++++ include/nether_Manager.h | 30 +++++ include/nether_Netlink.h | 33 ++++++ include/nether_PolicyBackend.h | 24 ++++ include/nether_Types.h | 192 +++++++++++++++++++++++++++++++ include/nether_Utils.h | 164 ++++++++++++++++++++++++++ src/nether_CynaraBackend.cpp | 156 +++++++++++++++++++++++++ src/nether_FileBackend.cpp | 101 ++++++++++++++++ src/nether_Main.cpp | 167 +++++++++++++++++++++++++++ src/nether_Manager.cpp | 253 +++++++++++++++++++++++++++++++++++++++++ src/nether_Netlink.cpp | 150 ++++++++++++++++++++++++ src/nether_NetworkUtils.cpp | 128 +++++++++++++++++++++ 14 files changed, 1546 insertions(+) create mode 100644 include/nether_CynaraBackend.h create mode 100644 include/nether_DummyBackend.h create mode 100644 include/nether_FileBackend.h create mode 100644 include/nether_Manager.h create mode 100644 include/nether_Netlink.h create mode 100644 include/nether_PolicyBackend.h create mode 100644 include/nether_Types.h create mode 100644 include/nether_Utils.h create mode 100644 src/nether_CynaraBackend.cpp create mode 100644 src/nether_FileBackend.cpp create mode 100644 src/nether_Main.cpp create mode 100644 src/nether_Manager.cpp create mode 100644 src/nether_Netlink.cpp create mode 100644 src/nether_NetworkUtils.cpp diff --git a/include/nether_CynaraBackend.h b/include/nether_CynaraBackend.h new file mode 100644 index 0000000..1242797 --- /dev/null +++ b/include/nether_CynaraBackend.h @@ -0,0 +1,50 @@ +#ifndef NETHER_CYNARA_BACKEND_H +#define NETHER_CYNARA_BACKEND_H + +// #ifdef HAVE_CYNARA + +#include +#include "nether_PolicyBackend.h" +#include + +#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); +} + +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); + + private: + cynara_async *cynaraContext; + NetherDescriptorStatus currentCynaraDescriptorStatus; + int currentCynaraDescriptor; + std::vector responseQueue; + int cynaraLastResult; +}; + +// #endif +#endif diff --git a/include/nether_DummyBackend.h b/include/nether_DummyBackend.h new file mode 100644 index 0000000..438e0f7 --- /dev/null +++ b/include/nether_DummyBackend.h @@ -0,0 +1,35 @@ +#ifndef NETHER_DUMMY_BACKEND_H +#define NETHER_DUMMY_BACKEND_H + + +#include "nether_PolicyBackend.h" + +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); + } +}; + +#endif diff --git a/include/nether_FileBackend.h b/include/nether_FileBackend.h new file mode 100644 index 0000000..4060153 --- /dev/null +++ b/include/nether_FileBackend.h @@ -0,0 +1,63 @@ +#ifndef NETHER_FILE_BACKEND_H +#define NETHER_FILE_BACKEND_H + +#include +#include +#include +#include +#include + +#include "nether_PolicyBackend.h" + +#define NETHER_POLICY_CREDS_DELIM ":" + +class NetherManager; + +enum PolicyFileTokens +{ + uidT, + gidT, + secctxT, + verdictT +}; + +struct PolicyEntry +{ + 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); + + 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; +}; + +#endif diff --git a/include/nether_Manager.h b/include/nether_Manager.h new file mode 100644 index 0000000..8e58d56 --- /dev/null +++ b/include/nether_Manager.h @@ -0,0 +1,30 @@ +#ifndef NETHER_MANAGER_H +#define NETHER_MANAGER_H + +#include "nether_Types.h" +#include "nether_DummyBackend.h" +#include "nether_Netlink.h" + + +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); + + private: + NetherPolicyBackend *netherPrimaryPolicyBackend, *netherBackupPolicyBackend; + NetherDummyBackend *netherFallbackPolicyBackend; + NetherNetlink *netherNetlink; + NetherConfig netherConfig; + int netlinkDescriptor, backendDescriptor, signalDescriptor; + sigset_t signalMask; +}; + +#endif diff --git a/include/nether_Netlink.h b/include/nether_Netlink.h new file mode 100644 index 0000000..8b934a7 --- /dev/null +++ b/include/nether_Netlink.h @@ -0,0 +1,33 @@ +#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 diff --git a/include/nether_PolicyBackend.h b/include/nether_PolicyBackend.h new file mode 100644 index 0000000..55879bf --- /dev/null +++ b/include/nether_PolicyBackend.h @@ -0,0 +1,24 @@ +#ifndef NETHER_POLICY_BACKEND_H +#define NETHER_POLICY_BACKEND_H + +#include "nether_Types.h" +#include "nether_Utils.h" + +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 (unknownStatus); } + virtual const bool processEvents() = 0; + + protected: + NetherConfig netherConfig; +}; + +#endif diff --git a/include/nether_Types.h b/include/nether_Types.h new file mode 100644 index 0000000..624abe8 --- /dev/null +++ b/include/nether_Types.h @@ -0,0 +1,192 @@ +#ifndef NETHER_TYPES_H +#define NETHER_TYPES_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "logger/logger.hpp" +#include "logger/backend-file.hpp" +#include "logger/backend-stderr.hpp" +#include "logger/backend-syslog.hpp" + +#ifdef HAVE_CYNARA + #define NETHER_PRIMARY_BACKEND cynaraBackend + #define NETHER_BACKUP_BACKEND fileBackend +#else + #define NETHER_PRIMARY_BACKEND fileBackend + #define NETHER_BACKUP_BACKEND dummyBackend +#endif + +#define NETHER_DEFAULT_VERDICT 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 stderrBackend + +enum NetherPolicyBackendType +{ + cynaraBackend, + fileBackend, + dummyBackend +}; + +enum NetherLogBackendType +{ + stderrBackend, + syslogBackend, + journalBackend, + logfileBackend, + nullBackend +}; + +enum NetherVerdict +{ + allow, + allowAndLog, + deny, + noVerdictYet +}; + +enum NetherDescriptorStatus +{ + readOnly, + writeOnly, + readWrite, + unknownStatus +}; + +enum NetherTransportType +{ + TCP, + UDP, + ICMP, + IGMP, + unknownTransportType +}; + +enum NetherProtocolType +{ + 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; +}; + +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 nodaemonMode = 0; + int queueNumber = 0; + std::string backupBackendArgs; + std::string primaryBackendArgs; + std::string logBackendArgs; + uint8_t markDeny = NETLINK_DROP_MARK; + uint8_t markAllowAndLog = NETLINK_ALLOWLOG_MARK; +}; + +class NetherVerdictListener +{ + 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; +}; + +class NetherProcessedPacketListener +{ + 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; +}; +#endif diff --git a/include/nether_Utils.h b/include/nether_Utils.h new file mode 100644 index 0000000..5d654e9 --- /dev/null +++ b/include/nether_Utils.h @@ -0,0 +1,164 @@ +#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); + +template +inline void deleteAndZero (Type& pointer) { delete pointer; pointer = nullptr; } + +static const NetherVerdict stringToVerdict (char *verdictAsString) +{ + if (verdictAsString) + { + if (strncasecmp (verdictAsString, "allow_log", 9) == 0) + return (allowAndLog); + if (strncasecmp (verdictAsString, "allow", 6) == 0) + return (allow); + if (strncasecmp (verdictAsString, "deny", 4) == 0) + return (deny); + } + return (allowAndLog); +} + +static const NetherPolicyBackendType stringToBackendType (char *backendAsString) +{ + if (strcasecmp (backendAsString, "cynara") == 0) + return (cynaraBackend); + if (strcasecmp (backendAsString, "file") == 0) + return (fileBackend); + if (strcasecmp (backendAsString, "dummy") == 0) + return (dummyBackend); + + return (dummyBackend); +} + +static const NetherLogBackendType stringToLogBackendType(char *backendAsString) +{ + if (strcasecmp (backendAsString, "stderr") == 0) + return (stderrBackend); + if (strcasecmp (backendAsString, "syslog") == 0) + return (syslogBackend); + if (strcasecmp (backendAsString, "journal") == 0) + return (journalBackend); + if (strcasecmp (backendAsString, "file") == 0) + return (logfileBackend); + if (strcasecmp (backendAsString, "null") == 0) + return (nullBackend); + + return (nullBackend); +} + +static const std::string logBackendTypeToString(const NetherLogBackendType backendType) +{ + switch (backendType) + { + case stderrBackend: + return ("stderr"); + case syslogBackend: + return ("syslog"); + case journalBackend: + return ("journal"); + case logfileBackend: + return ("file"); + case nullBackend: + return ("null"); + } + return ("null"); +} + +static const std::string backendTypeToString (const NetherPolicyBackendType backendType) +{ + switch (backendType) + { + case cynaraBackend: + return ("cynara"); + case fileBackend: + return ("file"); + case dummyBackend: + default: + return ("dummy"); + } +} + +static const std::string verdictToString (const NetherVerdict verdict) +{ + switch (verdict) + { + case allow: + return ("ALLOW"); + case allowAndLog: + return ("ALLOW_LOG"); + case deny: + return ("DENY"); + } +} + +static const std::string transportToString(const NetherTransportType transportType) +{ + switch (transportType) + { + case TCP: + return ("TCP"); + case UDP: + return ("UDP"); + case ICMP: + return ("ICMP"); + case IGMP: + return ("IGMP"); + case unknownTransportType: + default: + return ("UNKNOWN"); + } +} + +static const std::string protocolToString(const NetherProtocolType protocolType) +{ + switch (protocolType) + { + case IPv4: + return ("IPv4"); + case IPv6: + return ("IPv6"); + default: + return ("UNKNOWN"); + } +} + +static const 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()); +} + +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 +} +#endif diff --git a/src/nether_CynaraBackend.cpp b/src/nether_CynaraBackend.cpp new file mode 100644 index 0000000..10b426e --- /dev/null +++ b/src/nether_CynaraBackend.cpp @@ -0,0 +1,156 @@ +#include "nether_CynaraBackend.h" + +// #ifdef HAVE_CYNARA + +NetherCynaraBackend::NetherCynaraBackend(const NetherConfig &netherConfig) + : NetherPolicyBackend(netherConfig), currentCynaraDescriptor(0), + cynaraLastResult(CYNARA_API_UNKNOWN_ERROR) +{ + responseQueue.reserve(1024); +} + +NetherCynaraBackend::~NetherCynaraBackend() +{ +} + +const 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); +} + +void NetherCynaraBackend::statusCallback(int oldFd, int newFd, cynara_async_status status, void *data) +{ + LOGD("oldFd=" << oldFd << "newFd=" << newFd); + + NetherCynaraBackend *backend = static_cast(data); + + if (status == CYNARA_STATUS_FOR_READ) + backend->setCynaraDescriptor(newFd, readOnly); + + if (status == CYNARA_STATUS_FOR_RW) + backend->setCynaraDescriptor(newFd, readWrite); +} + +void NetherCynaraBackend::checkCallback(cynara_check_id check_id, + cynara_async_call_cause cause, + int response, + void *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); +} + +const bool NetherCynaraBackend::enqueueVerdict (const NetherPacket &packet) +{ + char user[NETHER_MAX_USER_LEN]; + cynara_check_id checkId; + + snprintf (user, sizeof(user), "%du", packet.uid); + + cynaraLastResult = cynara_async_check_cache(cynaraContext, packet.securityContext.c_str(), "", user, NETHER_CYNARA_INTERNET_PRIVILEGE); + + switch (cynaraLastResult) + { + case CYNARA_API_ACCESS_ALLOWED: + LOGD(cynaraErrorCodeToString(cynaraLastResult).c_str()); + return (castVerdict(packet, allow)); + + case CYNARA_API_ACCESS_DENIED: + LOGD(cynaraErrorCodeToString(cynaraLastResult).c_str()); + return (castVerdict(packet, 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.insert (responseQueue.begin() + 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.erase(responseQueue.begin() + checkId); + + if (cynaraResult == CYNARA_API_ACCESS_ALLOWED) + castVerdict (packetId, allow); + else + castVerdict (packetId, deny); + + return; + } + + LOGW("checkId=" << checkId << " has no assosiated packetId"); +} + +const bool NetherCynaraBackend::isValid() +{ + return ((cynaraLastResult == CYNARA_API_SUCCESS ? true : false) && cynaraContext); +} + +const int NetherCynaraBackend::getDescriptor() +{ + return (currentCynaraDescriptor); +} + +const NetherDescriptorStatus NetherCynaraBackend::getDescriptorStatus() +{ + return (currentCynaraDescriptorStatus); +} + +void NetherCynaraBackend::setCynaraDescriptor(const int _currentCynaraDescriptor, const NetherDescriptorStatus _currentCynaraDescriptorStatus) +{ + currentCynaraDescriptorStatus = _currentCynaraDescriptorStatus; + currentCynaraDescriptor = _currentCynaraDescriptor; +} + +const bool NetherCynaraBackend::processEvents() +{ + int ret = cynara_async_process(cynaraContext); + + if (ret == CYNARA_API_SUCCESS) + return (true); + + LOGW("cynara_async_process failed " << cynaraErrorCodeToString(ret)); + return (false); +} +//#endif diff --git a/src/nether_FileBackend.cpp b/src/nether_FileBackend.cpp new file mode 100644 index 0000000..b73281e --- /dev/null +++ b/src/nether_FileBackend.cpp @@ -0,0 +1,101 @@ +#include "nether_FileBackend.h" + +NetherFileBackend::NetherFileBackend (const NetherConfig &netherConfig) + : NetherPolicyBackend(netherConfig) +{ +} + +NetherFileBackend::~NetherFileBackend() +{ +} + +const bool NetherFileBackend::isValid() +{ + return (true); +} + +const bool NetherFileBackend::initialize() +{ + std::ifstream policyFile; + policyFile.open (netherConfig.backupBackendArgs, std::ifstream::in); + + if (!policyFile) + { + LOGE("Can't open policy file at: " << netherConfig.backupBackendArgs); + return (false); + } + + return (parsePolicyFile(policyFile)); +} + +const bool NetherFileBackend::reload() +{ + return (initialize()); +} + +const 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 (false); +} + +const 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"< NetherFileBackend::split(const std::string &str, const std::string &delim) +{ + std::vector tokens; + size_t start = 0, end = 0; + + 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 start=maxSize. Else use start=end+delimiter. + start = ((end > (std::string::npos - delim.size())) ? std::string::npos : end + delim.size()); + } + + return (tokens); +} diff --git a/src/nether_Main.cpp b/src/nether_Main.cpp new file mode 100644 index 0000000..1ab5e9b --- /dev/null +++ b/src/nether_Main.cpp @@ -0,0 +1,167 @@ +#include "nether_Types.h" +#include "nether_Utils.h" +#include "nether_Manager.h" + +using namespace std; +void showHelp(char *arg); + +int main(int argc, char *argv[]) +{ + int optionIndex, c; + struct NetherConfig netherConfig; + + static struct option longOptions[] = + { + {"nodaemon", no_argument, &netherConfig.nodaemonMode, 1}, + {"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'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + + while (1) + { + c = getopt_long (argc, argv, ":nl:L:V:p:P:b:B:q:m:M:h", longOptions, &optionIndex); + + if (c == -1) + break; + + switch (c) + { + case 0: + break; + + case 'n': + netherConfig.nodaemonMode = 1; + 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 'h': + showHelp (argv[0]); + exit (1); + } + } + switch (netherConfig.logBackend) + { + case stderrBackend: + logger::Logger::setLogBackend (new logger::StderrBackend(false)); + break; + case syslogBackend: + logger::Logger::setLogBackend (new logger::SyslogBackend()); + break; + case logfileBackend: + logger::Logger::setLogBackend (new logger::FileBackend(netherConfig.logBackendArgs)); + break; + default: + logger::Logger::setLogBackend (new logger::StderrBackend(false)); + break; + } + + LOGD("NETHER OPTIONS:" +#if defined(_DEBUG) + << " debug" +#endif + << " nodaemon=" << netherConfig.nodaemonMode + << " 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); + + NetherManager manager (netherConfig); + + if (!manager.initialize()) + { + LOGE("NetherManager failed to initialize, exiting"); + return (1); + } + + manager.process(); + + return (0); +} + +void showHelp(char *arg) +{ + cout<< "Usage:\t"<< arg << " [OPTIONS]\n\n"; + cout<< " -n,--nodaemon\t\t\t\tDon't run as daemon in the background\n"; + cout<< " -d,--debug\t\t\t\tRun in debug mode (implies --nodaemon)\n"; + cout<< " -l,--log=\t\t\tSet logging backend STDERR,SYSLOG,JOURNAL (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\tCYNARA,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\tCYNARA,FILE,NONE (defualt:"<< backendTypeToString(NETHER_BACKUP_BACKEND)<< ")\n"; + cout<< " -B,--backup-backend-args=\tBackup policy backend arguments\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<< " -h,--help\t\t\t\tshow help information\n"; +} diff --git a/src/nether_Manager.cpp b/src/nether_Manager.cpp new file mode 100644 index 0000000..0ec0ae6 --- /dev/null +++ b/src/nether_Manager.cpp @@ -0,0 +1,253 @@ +#include "nether_Manager.h" +#include "nether_CynaraBackend.h" +#include "nether_FileBackend.h" +#include "nether_DummyBackend.h" + +NetherManager::NetherManager(const NetherConfig &_netherConfig) + : netherConfig(_netherConfig), + netherPrimaryPolicyBackend(nullptr), + netherBackupPolicyBackend(nullptr), + netherFallbackPolicyBackend(nullptr) +{ + netherNetlink = new NetherNetlink(netherConfig); + netherNetlink->setListener (this); + + netherPrimaryPolicyBackend = getPolicyBackend (netherConfig); + netherPrimaryPolicyBackend->setListener (this); + + netherBackupPolicyBackend = getPolicyBackend (netherConfig, false); + netherBackupPolicyBackend->setListener (this); + + netherFallbackPolicyBackend = new NetherDummyBackend(netherConfig); +} + +NetherManager::~NetherManager() +{ + deleteAndZero (netherPrimaryPolicyBackend); + deleteAndZero (netherBackupPolicyBackend); + deleteAndZero (netherFallbackPolicyBackend); + deleteAndZero (netherNetlink); + close (signalDescriptor); +} + +const 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 (!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() +{ + NetherPacket receivedPacket; + int packetReadSize; + ssize_t signalRead; + struct signalfd_siginfo signalfdSignalInfo; + fd_set watchedReadDescriptorsSet, watchedWriteDescriptorsSet; + struct timeval timeoutSpecification; + char packetBuffer[NETHER_PACKET_BUFFER_SIZE] __attribute__ ((aligned)); + + while (1) + { + 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() == readOnly) + { + FD_SET(backendDescriptor, &watchedReadDescriptorsSet); + } + else if (netherPrimaryPolicyBackend->getDescriptorStatus() == readWrite) + { + FD_SET(backendDescriptor, &watchedReadDescriptorsSet); + FD_SET(backendDescriptor, &watchedWriteDescriptorsSet); + } + } + + timeoutSpecification.tv_sec = 240; + timeoutSpecification.tv_usec = 0; + + if (select (FD_SETSIZE, &watchedReadDescriptorsSet, &watchedWriteDescriptorsSet, NULL, &timeoutSpecification) < 0) + { + LOGE("select error " << strerror(errno)); + return (false); + } + + if (FD_ISSET(signalDescriptor, &watchedReadDescriptorsSet)) + { + LOGD("received signal"); + signalRead = read (signalDescriptor, &signalfdSignalInfo, sizeof(struct signalfd_siginfo)); + + if (signalRead != sizeof(struct signalfd_siginfo)) + { + LOGW("Received incomplete signal information, ignore"); + continue; + } + + 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"); + continue; + } + } + if (FD_ISSET(netlinkDescriptor, &watchedReadDescriptorsSet)) + { + LOGD("netlink descriptor active"); + + /* 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)) + { + continue; + } + 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"); + break; + } + } + + if (packetReadSize < 0 && errno == ENOBUFS) + { + LOGI("NetherManager::process losing packets! [bad things might happen]"); + continue; + } + + LOGE("NetherManager::process recv failed " << strerror(errno)); + break; + } + else if (FD_ISSET(backendDescriptor, &watchedReadDescriptorsSet) || FD_ISSET(backendDescriptor, &watchedWriteDescriptorsSet)) + { + LOGD("policy backend descriptor active"); + netherPrimaryPolicyBackend->processEvents(); + } + else + { + LOGD("select() timeout"); + } + } +} + +NetherConfig &NetherManager::getConfig() +{ + return (netherConfig); +} + +NetherPolicyBackend *NetherManager::getPolicyBackend(const NetherConfig &netherConfig, const bool primary) +{ + switch (primary ? netherConfig.primaryBackendType : netherConfig.backupBackendType) + { + case cynaraBackend: +#ifdef HAVE_CYNARA + return new NetherCynaraBackend(netherConfig); +#else + return new NetherDummyBackend(netherConfig); +#endif + case fileBackend: + return new NetherFileBackend(netherConfig); + case dummyBackend: + default: + return new NetherDummyBackend(netherConfig); + } +} + +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); +} + +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); +} diff --git a/src/nether_Netlink.cpp b/src/nether_Netlink.cpp new file mode 100644 index 0000000..ed2dd67 --- /dev/null +++ b/src/nether_Netlink.cpp @@ -0,0 +1,150 @@ +#include "nether_Netlink.h" + +NetherNetlink::NetherNetlink(NetherConfig &netherConfig) + : nfqHandle(nullptr), queueHandle(nullptr), nlif(nullptr), + queue(netherConfig.queueNumber), + NetherPacketProcessor(netherConfig) +{ +} + +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); +} + +int NetherNetlink::getDescriptor() +{ + if (nfqHandle) + return (nfq_fd(nfqHandle)); + else + LOGE("nfq not initialized"); +} + +const bool NetherNetlink::processPacket (char *packetBuffer, const int packetReadSize) +{ + if (nfq_handle_packet (nfqHandle, packetBuffer, packetReadSize)) + { + LOGE("nfq_handle_packet failed"); + return (false); + } + + return (true); +} + +int NetherNetlink::callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, 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)) + 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); +} + +void NetherNetlink::setVerdict(const u_int32_t packetId, const NetherVerdict verdict) +{ + int ret = 0; + LOGD("id=" << packetId << " verdict=" << verdictToString(verdict)); + + if (verdict == allow) + ret = nfq_set_verdict (queueHandle, packetId, NF_ACCEPT, 0, NULL); + if (verdict == deny) + ret = nfq_set_verdict2 (queueHandle, packetId, NF_ACCEPT, netherConfig.markDeny, 0, NULL); + if (verdict == 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() +{ + return (true); +} diff --git a/src/nether_NetworkUtils.cpp b/src/nether_NetworkUtils.cpp new file mode 100644 index 0000000..c6e1072 --- /dev/null +++ b/src/nether_NetworkUtils.cpp @@ -0,0 +1,128 @@ +#include +#include +#include "nether_Utils.h" + +#define IP_PROTOCOL_UDP (0x11) +#define IP_PROTOCOL_TCP (0x06) +#define IP_PROTOCOL_ICMP (0x01) +#define IP_PROTOCOL_IGMP (0x02) +#define IP_PROTOCOL_IPV6_ROUTE (0x2b) +#define IP_PROTOCOL_IPV6_FRAG (0x2c) +#define IP_PROTOCOL_IPV6_ICMP (0x3a) +#define IP_PROTOCOL_IPV6_NONXT (0x3b) +#define IP_PROTOCOL_IPV6_OPTS (0x3c) + +void decodePacket(NetherPacket &packet, unsigned char *payload) +{ + uint8_t ip_version = (payload[0] >> 4) & 0x0F; + + switch(ip_version) + { + case 4: + packet.protocolType = IPv4; + decodeIPv4Packet(packet, payload); + break; + case 6: + packet.protocolType = IPv6; + decodeIPv6Packet(packet, payload); + break; + default: + packet.transportType = unknownTransportType; + packet.protocolType = unknownProtocolType; + break; + } +} + +void decodeIPv6Packet(NetherPacket &packet, unsigned char *payload) +{ + const uint16_t start_of_ip_payload = 40; + uint8_t next_proto; + + memcpy(packet.localAddress, &payload[8], NETHER_NETWORK_IPV6_ADDR_LEN); + memcpy(packet.remoteAddress, &payload[24], NETHER_NETWORK_IPV6_ADDR_LEN); + + next_proto = payload[6]; + + switch(next_proto) + { + case IP_PROTOCOL_UDP: + packet.transportType = UDP; + decodeUdp(packet, &payload[start_of_ip_payload]); + break; + case IP_PROTOCOL_TCP: + packet.transportType = TCP; + decodeTcp(packet, &payload[start_of_ip_payload]); + break; + case IP_PROTOCOL_ICMP: + packet.transportType = ICMP; + break; + case IP_PROTOCOL_IGMP: + packet.transportType = IGMP; + break; + default: + packet.transportType = unknownTransportType; + break; + } +} + +void decodeIPv4Packet(NetherPacket &packet, unsigned char *payload) +{ + uint16_t start_of_ip_payload = 0; + uint8_t next_proto; + + start_of_ip_payload = (payload[0]&0x0F) << 2; + + memcpy(packet.localAddress, &payload[12], NETHER_NETWORK_IPV4_ADDR_LEN); + memcpy(packet.remoteAddress, &payload[16], NETHER_NETWORK_IPV4_ADDR_LEN); + + next_proto = payload[9]; + switch(next_proto) + { + case IP_PROTOCOL_UDP: + packet.transportType = UDP; + decodeUdp(packet, &payload[start_of_ip_payload]); + break; + case IP_PROTOCOL_TCP: + packet.transportType = TCP; + decodeTcp(packet, &payload[start_of_ip_payload]); + break; + case IP_PROTOCOL_ICMP: + packet.transportType = ICMP; + break; + case IP_PROTOCOL_IGMP: + packet.transportType = IGMP; + default: + packet.transportType = unknownTransportType; + break; + } +} + +void decodeTcp(NetherPacket &packet, unsigned char *payload) +{ + 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]); + +} + +const std::string ipAddressToString(const char *src, enum NetherProtocolType type) +{ + switch(type) + { + case IPv4: + return (stringFormat("%u.%u.%u.%u", src[0]&0xff,src[1]&0xff,src[2]&0xff,src[3]&0xff)); + case 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 ba6b09873a10dc2616c89e177db798e76f59ae4a Mon Sep 17 00:00:00 2001 From: RomanKubiak Date: Thu, 16 Jul 2015 16:55:05 +0200 Subject: [PATCH 3/9] Build subsystem for nether (cmake, codeblocks, spec) Change-Id: I35e39dc7e34087126b0a8aa2999cd0f7eb733fe3 --- CMakeLists.txt | 5 ++ nether.cbp | 119 ++++++++++++++++++++++++++++++++++++++++++++++ packaging/nether.manifest | 5 ++ packaging/nether.spec | 66 +++++++++++++++++++++++++ src/CMakeLists.txt | 30 ++++++++++++ 5 files changed, 225 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 nether.cbp create mode 100644 packaging/nether.manifest create mode 100644 packaging/nether.spec create mode 100644 src/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d372f16 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,5 @@ +CMAKE_MINIMUM_REQUIRED (VERSION 2.6) +PROJECT (nether) +INCLUDE(FindPkgConfig) +SET (CMAKE_CXX_FLAGS "-std=c++11") +ADD_SUBDIRECTORY(src) diff --git a/nether.cbp b/nether.cbp new file mode 100644 index 0000000..aeedfa5 --- /dev/null +++ b/nether.cbp @@ -0,0 +1,119 @@ + + + + + + diff --git a/packaging/nether.manifest b/packaging/nether.manifest new file mode 100644 index 0000000..2a0cec5 --- /dev/null +++ b/packaging/nether.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/nether.spec b/packaging/nether.spec new file mode 100644 index 0000000..0482d03 --- /dev/null +++ b/packaging/nether.spec @@ -0,0 +1,66 @@ +Name: nether +Epoch: 1 +Version: 0.0.1 +Release: 0 +Source0: %{name}-%{version}.tar.gz +License: Apache-2.0 +Group: Security/Other +Summary: Daemon for enforcing network privileges +BuildRequires: cmake +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: libnetfilter_queue-devel +Requires: iptables + +%description +This package provides a daemon used to manage zones - start, stop and switch +between them. A process from inside a zone can request a switch of context +(display, input devices) to the other zone. + +%files +%manifest packaging/nether.manifest +%defattr(644,root,root,755) +%attr(755,root,root) %{_bindir}/nether +%dir /etc/nether +%config /etc/nether/nether.policy +%config /etc/nether/setrules.sh +%config /etc/nether/nether.rules +%prep +%setup -q + +%build +%{!?build_type:%define build_type "RELEASE"} + +%if %{build_type} == "DEBUG" || %{build_type} == "PROFILING" || %{build_type} == "CCOV" + CFLAGS="$CFLAGS -Wp,-U_FORTIFY_SOURCE" + CXXFLAGS="$CXXFLAGS -Wp,-U_FORTIFY_SOURCE" +%endif + +%cmake . -DVERSION=%{version} \ + -DCMAKE_BUILD_TYPE=%{build_type} \ + -DSCRIPT_INSTALL_DIR=%{script_dir} \ + -DSYSTEMD_UNIT_DIR=%{_unitdir} +make -k %{?jobs:-j%jobs} + +%install +%make_install + +%clean +rm -rf %{buildroot} + +%post +# Refresh systemd services list after installation +if [ $1 == 1 ]; then + systemctl daemon-reload || : +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 +if [ $1 == 0 ]; then + systemctl stop nether.service || : +fi + +%postun +# Refresh systemd services list after uninstall/upgrade +systemctl daemon-reload || : diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..3585b3d --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,30 @@ +FILE (GLOB NETHER_SOURCES *.cpp) +FILE (GLOB VASUM_LOGGER logger/*.cpp) +PKG_CHECK_MODULES (CYNARA cynara-client-async QUIET) +PKG_CHECK_MODULES (NETFILTER libnetfilter_queue REQUIRED) +PKG_CHECK_MODULES (LOGGER libsystemd-journal QUIET) + +ADD_EXECUTABLE(nether ${NETHER_SOURCES} ${VASUM_LOGGER}) + +INCLUDE_DIRECTORIES ( + ../include + ${EXTERNAL_INCLUDE_DIRS} + ${CYNARA_INCLUDE_DIRS} + ${NETFILTER_INCLUDE_DIRS} + ${LOGGER_INCLUDE_DIRS} + ) +if(CYNARA_FOUND) + ADD_DEFINITIONS (-DHAVE_CYNARA=${CYNARA_FOUND}) +endif() + +if(LOGGER_FOUND) + ADD_DEFINITIONS (-DHAVE_SYSTEMD_JOURNAL=${LOGGER_FOUND}) +endif() + +IF(CMAKE_BUILD_TYPE MATCHES DEBUG) + ADD_DEFINITIONS (-D_DEBUG=1) +ENDIF(CMAKE_BUILD_TYPE MATCHES DEBUG) + +TARGET_LINK_LIBRARIES(nether ${CYNARA_LIBRARIES} + ${NETFILTER_LIBRARIES} + ${LOGGER_LIBRARIES} ) \ No newline at end of file -- 2.7.4 From 161e2ea2dbf56de7189a22be0b5faaa8de25238e Mon Sep 17 00:00:00 2001 From: RomanKubiak Date: Thu, 16 Jul 2015 16:56:05 +0200 Subject: [PATCH 4/9] Included vasum logger class. Some modifications - added an option to disable colours in stderr logger - added a syslog backend if journal is not available - added a file backend Change-Id: Id6ed1c56f871be8970879277b331b26d0e3969f3 --- include/logger/backend-file.hpp | 22 +++++++ include/logger/backend-journal.hpp | 46 +++++++++++++ include/logger/backend-null.hpp | 46 +++++++++++++ include/logger/backend-stderr.hpp | 49 ++++++++++++++ include/logger/backend-syslog.hpp | 19 ++++++ include/logger/backend.hpp | 49 ++++++++++++++ include/logger/ccolor.hpp | 53 +++++++++++++++ include/logger/config.hpp | 78 ++++++++++++++++++++++ include/logger/formatter.hpp | 50 ++++++++++++++ include/logger/level.hpp | 55 ++++++++++++++++ include/logger/logger-scope.hpp | 78 ++++++++++++++++++++++ include/logger/logger.hpp | 85 ++++++++++++++++++++++++ src/logger/backend-file.cpp | 22 +++++++ src/logger/backend-journal.cpp | 72 ++++++++++++++++++++ src/logger/backend-stderr.cpp | 61 +++++++++++++++++ src/logger/backend-syslog.cpp | 42 ++++++++++++ src/logger/ccolor.cpp | 41 ++++++++++++ src/logger/formatter.cpp | 131 +++++++++++++++++++++++++++++++++++++ src/logger/level.cpp | 71 ++++++++++++++++++++ src/logger/logger-scope.cpp | 60 +++++++++++++++++ src/logger/logger.cpp | 76 +++++++++++++++++++++ 21 files changed, 1206 insertions(+) create mode 100644 include/logger/backend-file.hpp create mode 100644 include/logger/backend-journal.hpp create mode 100644 include/logger/backend-null.hpp create mode 100644 include/logger/backend-stderr.hpp create mode 100644 include/logger/backend-syslog.hpp create mode 100644 include/logger/backend.hpp create mode 100644 include/logger/ccolor.hpp create mode 100644 include/logger/config.hpp create mode 100644 include/logger/formatter.hpp create mode 100644 include/logger/level.hpp create mode 100644 include/logger/logger-scope.hpp create mode 100644 include/logger/logger.hpp create mode 100644 src/logger/backend-file.cpp create mode 100644 src/logger/backend-journal.cpp create mode 100644 src/logger/backend-stderr.cpp create mode 100644 src/logger/backend-syslog.cpp create mode 100644 src/logger/ccolor.cpp create mode 100644 src/logger/formatter.cpp create mode 100644 src/logger/level.cpp create mode 100644 src/logger/logger-scope.cpp create mode 100644 src/logger/logger.cpp diff --git a/include/logger/backend-file.hpp b/include/logger/backend-file.hpp new file mode 100644 index 0000000..9a108d1 --- /dev/null +++ b/include/logger/backend-file.hpp @@ -0,0 +1,22 @@ +#ifndef COMMON_LOGGER_BACKEND_FILE_HPP +#define COMMON_LOGGER_BACKEND_FILE_HPP + +#include "logger/backend.hpp" + +namespace logger { + +class FileBackend : public LogBackend { +public: + FileBackend(const std::string &_filePath) : filePath(_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 filePath; +}; + +} // namespace logger + +#endif diff --git a/include/logger/backend-journal.hpp b/include/logger/backend-journal.hpp new file mode 100644 index 0000000..e566ed1 --- /dev/null +++ b/include/logger/backend-journal.hpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Dariusz Michaluk + * + * 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 Dariusz Michaluk (d.michaluk@samsung.com) + * @brief Systemd journal backend for logger + */ + +#ifndef COMMON_LOGGER_BACKEND_JOURNAL_HPP +#define COMMON_LOGGER_BACKEND_JOURNAL_HPP + +#include "logger/backend.hpp" + +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; +}; + +} // namespace logger + +#endif // COMMON_LOGGER_BACKEND_JOURNAL_HPP diff --git a/include/logger/backend-null.hpp b/include/logger/backend-null.hpp new file mode 100644 index 0000000..4a7e8a9 --- /dev/null +++ b/include/logger/backend-null.hpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Pawel Broda + * + * 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 Pawel Broda (p.broda@partner.samsung.com) + * @brief Null backend for logger + */ + +#ifndef COMMON_LOGGER_BACKEND_NULL_HPP +#define COMMON_LOGGER_BACKEND_NULL_HPP + +#include "logger/backend.hpp" + +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 {} +}; + +} // namespace logger + +#endif // COMMON_LOGGER_BACKEND_NULL_HPP diff --git a/include/logger/backend-stderr.hpp b/include/logger/backend-stderr.hpp new file mode 100644 index 0000000..919e24e --- /dev/null +++ b/include/logger/backend-stderr.hpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Pawel Broda + * + * 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 Pawel Broda (p.broda@partner.samsung.com) + * @brief Stderr backend for logger + */ + +#ifndef COMMON_LOGGER_BACKEND_STDERR_HPP +#define COMMON_LOGGER_BACKEND_STDERR_HPP + +#include "logger/backend.hpp" + +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; +}; + +} // namespace logger + +#endif // COMMON_LOGGER_BACKEND_STDERR_HPP diff --git a/include/logger/backend-syslog.hpp b/include/logger/backend-syslog.hpp new file mode 100644 index 0000000..23450b5 --- /dev/null +++ b/include/logger/backend-syslog.hpp @@ -0,0 +1,19 @@ +#ifndef COMMON_LOGGER_BACKEND_SYSLOG_HPP +#define COMMON_LOGGER_BACKEND_SYSLOG_HPP + +#include "logger/backend.hpp" + +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; +}; + +} // namespace logger + +#endif diff --git a/include/logger/backend.hpp b/include/logger/backend.hpp new file mode 100644 index 0000000..99b0c49 --- /dev/null +++ b/include/logger/backend.hpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Pawel Broda + * + * 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 Pawel Broda (p.broda@partner.samsung.com) + * @brief Logging backend + */ + +#ifndef COMMON_LOGGER_BACKEND_HPP +#define COMMON_LOGGER_BACKEND_HPP + +#include "logger/level.hpp" + +#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 + +#endif // COMMON_LOGGER_BACKEND_HPP diff --git a/include/logger/ccolor.hpp b/include/logger/ccolor.hpp new file mode 100644 index 0000000..47cc25e --- /dev/null +++ b/include/logger/ccolor.hpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Dariusz Michaluk + * + * 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 Dariusz Michaluk (d.michaluk@samsung.com) + * @brief Console color for StderrBackend logger + */ + +#ifndef COMMON_LOGGER_CCOLOR_HPP +#define COMMON_LOGGER_CCOLOR_HPP + +#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 + +#endif // COMMON_LOGGER_CCOLOR_HPP diff --git a/include/logger/config.hpp b/include/logger/config.hpp new file mode 100644 index 0000000..753430e --- /dev/null +++ b/include/logger/config.hpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Lukasz Pawelczyk (l.pawelczyk@partner.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 Lukasz Pawelczyk (l.pawelczyk@partner.samsung.com) + * @brief Configuration file for the code + */ + + +#ifndef COMMON_CONFIG_HPP +#define COMMON_CONFIG_HPP + + +#ifdef __clang__ +#define CLANG_VERSION (__clang__major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) +#endif // __clang__ + +#if defined __GNUC__ && !defined __clang__ // clang also defines GCC versions +#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#endif // __GNUC__ + + +#ifdef GCC_VERSION + +#if GCC_VERSION < 40800 +// GCC 4.8 is the first where those defines are not required for +// std::this_thread::sleep_for() and ::yield(). They might exist though +// in previous versions depending on the build configuration of the GCC. +#ifndef _GLIBCXX_USE_NANOSLEEP +#define _GLIBCXX_USE_NANOSLEEP +#endif // _GLIBCXX_USE_NANOSLEEP +#ifndef _GLIBCXX_USE_SCHED_YIELD +#define _GLIBCXX_USE_SCHED_YIELD +#endif // _GLIBCXX_USE_SCHED_YIELD +#endif // GCC_VERSION < 40800 + +#if GCC_VERSION < 40700 +// Those appeared in 4.7 with full c++11 support +#define final +#define override +#define thread_local __thread // use GCC extension instead of C++11 +#define steady_clock monotonic_clock +#endif // GCC_VERSION < 40700 + +#endif // GCC_VERSION + +// Variadic macros support for boost preprocessor should be enabled +// manually for clang since they are marked as untested feature +// (boost trunk if fixed but the latest 1.55 version is not, +// see boost/preprocessor/config/config.hpp) +#ifdef __clang__ +#define BOOST_PP_VARIADICS 1 +#endif + +// This has to be defined always when the boost has not been compiled +// using C++11. Headers detect that you are compiling using C++11 and +// blindly and wrongly assume that boost has been as well. +#ifndef BOOST_NO_CXX11_SCOPED_ENUMS +#define BOOST_NO_CXX11_SCOPED_ENUMS 1 +#endif + +#endif // COMMON_CONFIG_HPP diff --git a/include/logger/formatter.hpp b/include/logger/formatter.hpp new file mode 100644 index 0000000..3af0763 --- /dev/null +++ b/include/logger/formatter.hpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Dariusz Michaluk + * + * 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 Dariusz Michaluk (d.michaluk@samsung.com) + * @brief Helper formatter for logger + */ + +#ifndef COMMON_LOGGER_FORMATTER_HPP +#define COMMON_LOGGER_FORMATTER_HPP + +#include "logger/level.hpp" + +#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 + +#endif // COMMON_LOGGER_FORMATTER_HPP diff --git a/include/logger/level.hpp b/include/logger/level.hpp new file mode 100644 index 0000000..7902301 --- /dev/null +++ b/include/logger/level.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Dariusz Michaluk (d.michaluk@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 Dariusz Michaluk (d.michaluk@samsung.com) + * @brief LogLevel + */ + +#ifndef COMMON_LOGGER_LEVEL_HPP +#define COMMON_LOGGER_LEVEL_HPP + +#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 + +#endif // COMMON_LOGGER_LEVEL_HPP diff --git a/include/logger/logger-scope.hpp b/include/logger/logger-scope.hpp new file mode 100644 index 0000000..cefd912 --- /dev/null +++ b/include/logger/logger-scope.hpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Lukasz Kostyra + * + * 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 Lukasz Kostyra (l.kostyra@samsung.com) + * @brief Scope logger class declaration + */ + +#ifndef COMMON_LOGGER_LOGGER_SCOPE_HPP +#define COMMON_LOGGER_LOGGER_SCOPE_HPP + +#include +#include + +namespace logger { + +class SStreamWrapper +{ +public: + operator std::string() const; + + template + SStreamWrapper& operator<<(const T& b) + { + this->mSStream << b; + return *this; + } + +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; +}; + +} // namespace logger + +// macro to automatically create LoggerScope object +#define LOGS(MSG) logger::LoggerScope logScopeObj(__FILE__, __LINE__, __func__, \ + logger::SStreamWrapper() << MSG, \ + PROJECT_SOURCE_DIR) + +#endif // COMMON_LOGGER_LOGGER_SCOPE_HPP diff --git a/include/logger/logger.hpp b/include/logger/logger.hpp new file mode 100644 index 0000000..d596a20 --- /dev/null +++ b/include/logger/logger.hpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jan Olszak + * + * 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 Jan Olszak (j.olszak@samsung.com) + * @brief Logger + */ + +#ifndef COMMON_LOGGER_LOGGER_HPP +#define COMMON_LOGGER_LOGGER_HPP + +#include "logger/level.hpp" +#include "logger/backend-file.hpp" +#include "logger/backend-stderr.hpp" + +#include +#include + +#ifndef PROJECT_SOURCE_DIR +#define PROJECT_SOURCE_DIR "" +#endif + +namespace logger { + +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); + + static void setLogLevel(const LogLevel level); + static void setLogLevel(const std::string& level); + static LogLevel getLogLevel(void); + static void setLogBackend(LogBackend* pBackend); +}; + +} // namespace logger + +#define LOG(SEVERITY, MESSAGE) \ + do { \ + if (logger::Logger::getLogLevel() <= logger::LogLevel::SEVERITY) { \ + std::ostringstream messageStream__; \ + messageStream__ << MESSAGE; \ + logger::Logger::logMessage(logger::LogLevel::SEVERITY, \ + messageStream__.str(), \ + __FILE__, \ + __LINE__, \ + __func__, \ + PROJECT_SOURCE_DIR); \ + } \ + } while (0) + +#define LOGE(MESSAGE) LOG(ERROR, MESSAGE) +#define LOGW(MESSAGE) LOG(WARN, MESSAGE) +#define LOGI(MESSAGE) LOG(INFO, MESSAGE) +#if defined(_DEBUG) +#define LOGD(MESSAGE) LOG(DEBUG, MESSAGE) +#else +#define LOGD(MESSAGE) do {} while (0) +#endif +#define LOGH(MESSAGE) LOG(HELP, MESSAGE) +#define LOGT(MESSAGE) LOG(TRACE, MESSAGE) + +#endif // COMMON_LOGGER_LOGGER_HPP diff --git a/src/logger/backend-file.cpp b/src/logger/backend-file.cpp new file mode 100644 index 0000000..fcfd1bf --- /dev/null +++ b/src/logger/backend-file.cpp @@ -0,0 +1,22 @@ +#include "logger/config.hpp" +#include "logger/formatter.hpp" +#include "logger/backend-file.hpp" + +#include + +namespace logger { + +void FileBackend::log(LogLevel logLevel, + const std::string& file, + const unsigned int& line, + const std::string& func, + const std::string& message) +{ + std::ofstream out(filePath, std::ios::app); + out << LogFormatter::getHeader(logLevel, file, line, func); + out << message; + out << "\n"; +} + + +} diff --git a/src/logger/backend-journal.cpp b/src/logger/backend-journal.cpp new file mode 100644 index 0000000..85cb46f --- /dev/null +++ b/src/logger/backend-journal.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Dariusz Michaluk + * + * 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 Dariusz Michaluk (d.michaluk@samsung.com) + * @brief Systemd journal backend for logger + */ +#ifdef HAVE_SYSTEMD_JOURNAL +#include "logger/config.hpp" +#include "logger/backend-journal.hpp" + +#define SD_JOURNAL_SUPPRESS_LOCATION +#include + +namespace logger { + +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 + } +} + +} // 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); +} + +} // namespace logger +#endif \ No newline at end of file diff --git a/src/logger/backend-stderr.cpp b/src/logger/backend-stderr.cpp new file mode 100644 index 0000000..36c71ac --- /dev/null +++ b/src/logger/backend-stderr.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Pawel Broda + * + * 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 Pawel Broda (p.broda@partner.samsung.com) + * @brief Stderr backend for logger + */ + +#include "logger/config.hpp" +#include "logger/backend-stderr.hpp" +#include "logger/formatter.hpp" + +#include + +namespace logger { + +void StderrBackend::log(LogLevel logLevel, + const std::string& file, + const unsigned int& line, + const std::string& func, + const std::string& message) +{ + 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 + + 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() : ""); + } + } +} + +} // namespace logger diff --git a/src/logger/backend-syslog.cpp b/src/logger/backend-syslog.cpp new file mode 100644 index 0000000..0542e46 --- /dev/null +++ b/src/logger/backend-syslog.cpp @@ -0,0 +1,42 @@ +#include "logger/config.hpp" +#include "logger/formatter.hpp" +#include "logger/backend-syslog.hpp" + +#include +#include +namespace logger { + +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 + } +} + +} // 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()); +} + +} diff --git a/src/logger/ccolor.cpp b/src/logger/ccolor.cpp new file mode 100644 index 0000000..9cc652d --- /dev/null +++ b/src/logger/ccolor.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Dariusz Michaluk + * + * 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 Dariusz Michaluk (d.michaluk@samsung.com) + * @brief Console color for StderrBackend logger + */ + +#include "logger/config.hpp" +#include "logger/ccolor.hpp" + +#include + +namespace logger { + +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 new file mode 100644 index 0000000..815a111 --- /dev/null +++ b/src/logger/formatter.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Dariusz Michaluk + * + * 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 Dariusz Michaluk (d.michaluk@samsung.com) + * @brief Helper formatter for logger + */ + +#include "logger/config.hpp" +#include "logger/formatter.hpp" +#include "logger/ccolor.hpp" + +#include +#include +#include +#include +#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) +{ + 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 new file mode 100644 index 0000000..3b74205 --- /dev/null +++ b/src/logger/level.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jan Olszak + * + * 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 Jan Olszak (j.olszak@samsung.com) + * @brief Functions to handle LogLevel + */ + +#include "logger/config.hpp" +#include "logger/level.hpp" + +#include +#include + +namespace logger { + +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"); + } +} + +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 new file mode 100644 index 0000000..a977adc --- /dev/null +++ b/src/logger/logger-scope.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Lukasz Kostyra + * + * 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 Lukasz Kostyra (l.kostyra@samsung.com) + * @brief Scope logger class implementation + */ + +#include "logger/logger-scope.hpp" +#include "logger/logger.hpp" + +namespace logger { + +SStreamWrapper::operator std::string() const +{ + 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); + } +} + +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 new file mode 100644 index 0000000..ec0855b --- /dev/null +++ b/src/logger/logger.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Pawel Broda + * + * 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 Pawel Broda (p.broda@partner.samsung.com) + * @brief Logger + */ + +#include "logger/config.hpp" +#include "logger/logger.hpp" +#include "logger/formatter.hpp" +#include "logger/backend-null.hpp" + +#include +#include + +namespace logger { + +namespace { + +volatile LogLevel gLogLevel = LogLevel::DEBUG; +std::unique_ptr gLogBackendPtr(new NullLogger()); +std::mutex gLogMutex; + +} // 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::setLogLevel(const LogLevel level) +{ + gLogLevel = level; +} + +void Logger::setLogLevel(const std::string& level) +{ + gLogLevel = parseLogLevel(level); +} + +LogLevel Logger::getLogLevel(void) +{ + return gLogLevel; +} + +void Logger::setLogBackend(LogBackend* pBackend) +{ + std::unique_lock lock(gLogMutex); + gLogBackendPtr.reset(pBackend); +} + +} // namespace logger -- 2.7.4 From 9d4c95ce5c204804ece99d541f7e4fe6550c6973 Mon Sep 17 00:00:00 2001 From: RomanKubiak Date: Thu, 16 Jul 2015 16:57:12 +0200 Subject: [PATCH 5/9] Added nether helper scripts and a simple example policy for the file backend. Change-Id: Ife2f173d9964cb9f65a9c88d8779872020ab6e46 --- config/nether.policy | 7 ++++++ config/nether.rules | 29 ++++++++++++++++++++++ config/setrules.sh | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 config/nether.policy create mode 100644 config/nether.rules create mode 100755 config/setrules.sh diff --git a/config/nether.policy b/config/nether.policy new file mode 100644 index 0000000..324a7e3 --- /dev/null +++ b/config/nether.policy @@ -0,0 +1,7 @@ +# Nether policy +# $UID:$GID:$SECCTX ALLOW|DENY|ALLOW_LOG +# + +0::_:ALLOW +5002::_:DENY +1354787703::_:ALLOW \ No newline at end of file diff --git a/config/nether.rules b/config/nether.rules new file mode 100644 index 0000000..72d4ebe --- /dev/null +++ b/config/nether.rules @@ -0,0 +1,29 @@ +# nether iptables rules +*nat +:PREROUTING ACCEPT [214977:18048203] +:INPUT ACCEPT [24506:3910785] +:OUTPUT ACCEPT [46836:3016993] +:POSTROUTING ACCEPT [45527:2930737] +COMMIT +*mangle +:PREROUTING ACCEPT [1008811:2134498122] +:INPUT ACCEPT [948545:2129919738] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [816152:74580343] +:POSTROUTING ACCEPT [824147:75308906] +-A OUTPUT -p tcp -m state --state NEW -m tcp --dport 443 -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] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [805408:74228055] +:NETHER-ALLOWLOG - [0:0] +:NETHER-DENY - [0:0] +-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 +-A NETHER-DENY -j AUDIT --type reject +-A NETHER-DENY -j REJECT --reject-with icmp-port-unreachable +COMMIT diff --git a/config/setrules.sh b/config/setrules.sh new file mode 100755 index 0000000..94e6e40 --- /dev/null +++ b/config/setrules.sh @@ -0,0 +1,68 @@ +#!/bin/bash +DENY_CHAIN="NETHER-DENY" +ALLOWLOG_CHAIN="NETHER-ALLOWLOG" +TEST_HOST="198.145.20.7" +TEST_PORT=443 +TEST_PROTO="tcp" +TEST_QUEUE=0 +AUDITCTL=auditctl +DENY_MARK="0x3" +ALLOWLOG_MARK="0x4" + +function runcmd { + echo -ne "\t>> $@\n" + $@ +} + +function clean { + echo "Cleanup" + echo + iptables -t mangle -D OUTPUT -m state --state NEW -p $TEST_PROTO -d $TEST_HOST --dport $TEST_PORT -j NFQUEUE --queue-num 0 --queue-bypass 2> /dev/null + iptables -D OUTPUT -m mark --mark $DENY_MARK -j $DENY_CHAIN 2> /dev/null + iptables -D OUTPUT -m mark --mark $ALLOWLOG_MARK -j $ALLOWLOG_CHAIN 2> /dev/null + iptables -F $DENY_CHAIN 2> /dev/null + iptables -F $ALLOWLOG_CHAIN 2> /dev/null + iptables -X $DENY_CHAIN 2> /dev/null + iptables -X $ALLOWLOG_CHAIN 2> /dev/null + echo +} + +function create { + echo "Creating chain" + echo + runcmd iptables -N $DENY_CHAIN + runcmd iptables -N $ALLOWLOG_CHAIN + runcmd iptables -A $DENY_CHAIN -j AUDIT --type REJECT + runcmd iptables -A $DENY_CHAIN -j REJECT + runcmd iptables -A $ALLOWLOG_CHAIN -j AUDIT --type ACCEPT + echo +} + +function create_rules { + echo "Writing rules to output chain $OUTPUT_CHAIN" + echo + runcmd iptables -t mangle -A OUTPUT -m state --state NEW -p $TEST_PROTO -d $TEST_HOST --dport $TEST_PORT -j NFQUEUE --queue-num 0 --queue-bypass + runcmd iptables -A OUTPUT -m mark --mark $DENY_MARK -j $DENY_CHAIN + runcmd iptables -A OUTPUT -m mark --mark $ALLOWLOG_MARK -j $ALLOWLOG_CHAIN + echo +} + +function enable_audit { + if type $AUDITCTL; then + echo -n "Enable audit: " + runcmd $AUDITCTL -e 1 >/dev/null + if [ $? == 0 ]; then + echo "OK" + else + echo "Failed" + fi + else + echo "$AUDITCTL does not exist, can't enable audit" + fi + echo +} + +clean +create +create_rules +enable_audit -- 2.7.4 From 98fd309ef9847664213bf4ba963467fc00f328a2 Mon Sep 17 00:00:00 2001 From: RomanKubiak Date: Thu, 16 Jul 2015 16:57:24 +0200 Subject: [PATCH 6/9] Added the README.md file for github Added license info to files Using unique_ptr<> in manager Broke up the process() method in manager Change-Id: I980d281d7decae6d1e23b9f5937117449ac627e3 --- README.md | 15 +++ config/setrules.sh | 19 +++- include/logger/backend-file.hpp | 28 ++++- include/logger/backend-syslog.hpp | 24 +++++ include/nether_CynaraBackend.h | 24 +++++ include/nether_FileBackend.h | 24 +++++ include/nether_Manager.h | 32 +++++- include/nether_Netlink.h | 24 +++++ include/nether_PolicyBackend.h | 24 +++++ include/nether_Types.h | 25 +++++ include/nether_Utils.h | 25 +++++ nether.cbp | 8 +- src/CMakeLists.txt | 21 ++-- src/logger/backend-file.cpp | 30 +++++- src/logger/backend-journal.cpp | 2 +- src/logger/backend-syslog.cpp | 26 ++++- src/nether_CynaraBackend.cpp | 28 ++++- src/nether_FileBackend.cpp | 24 +++++ src/nether_Main.cpp | 29 ++++++ src/nether_Manager.cpp | 213 ++++++++++++++++++++++---------------- src/nether_Netlink.cpp | 24 +++++ src/nether_NetworkUtils.cpp | 55 +++++++--- 22 files changed, 596 insertions(+), 128 deletions(-) create mode 100644 README.md mode change 100755 => 100644 config/setrules.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..58650fa --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# nether + +An application firewall that enforces the "internet" +privileges in Tizen. It uses Cynara as a policy backend +and the NFQUEUE target in netfilter to make decisiions +about outgoing connections and network packets. + +The policy backend can be re-implemented by overloading +the NetherPolicyBackend class (there is a simple File based +backend included for testing). + +A default policy can be specified in case the policy +backend stops working. + + diff --git a/config/setrules.sh b/config/setrules.sh old mode 100755 new mode 100644 index 94e6e40..9c2d168 --- a/config/setrules.sh +++ b/config/setrules.sh @@ -1,3 +1,20 @@ +# +# Copyright (c) 2014 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 +# #!/bin/bash DENY_CHAIN="NETHER-DENY" ALLOWLOG_CHAIN="NETHER-ALLOWLOG" @@ -30,7 +47,7 @@ function clean { function create { echo "Creating chain" echo - runcmd iptables -N $DENY_CHAIN + runcmd iptables -N $DENY_CHAIN runcmd iptables -N $ALLOWLOG_CHAIN runcmd iptables -A $DENY_CHAIN -j AUDIT --type REJECT runcmd iptables -A $DENY_CHAIN -j REJECT diff --git a/include/logger/backend-file.hpp b/include/logger/backend-file.hpp index 9a108d1..2fc4822 100644 --- a/include/logger/backend-file.hpp +++ b/include/logger/backend-file.hpp @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2014 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 File backend for logger + */ + #ifndef COMMON_LOGGER_BACKEND_FILE_HPP #define COMMON_LOGGER_BACKEND_FILE_HPP @@ -7,14 +31,14 @@ namespace logger { class FileBackend : public LogBackend { public: - FileBackend(const std::string &_filePath) : filePath(_filePath) {} + 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 filePath; + std::string mfilePath; }; } // namespace logger diff --git a/include/logger/backend-syslog.hpp b/include/logger/backend-syslog.hpp index 23450b5..045fdec 100644 --- a/include/logger/backend-syslog.hpp +++ b/include/logger/backend-syslog.hpp @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2014 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 Syslog backend for logger + */ + #ifndef COMMON_LOGGER_BACKEND_SYSLOG_HPP #define COMMON_LOGGER_BACKEND_SYSLOG_HPP diff --git a/include/nether_CynaraBackend.h b/include/nether_CynaraBackend.h index 1242797..a8bc88e 100644 --- a/include/nether_CynaraBackend.h +++ b/include/nether_CynaraBackend.h @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2014 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 Cynara policy backend for nether + */ + #ifndef NETHER_CYNARA_BACKEND_H #define NETHER_CYNARA_BACKEND_H diff --git a/include/nether_FileBackend.h b/include/nether_FileBackend.h index 4060153..213b87f 100644 --- a/include/nether_FileBackend.h +++ b/include/nether_FileBackend.h @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2014 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 File policy backend for nether + */ + #ifndef NETHER_FILE_BACKEND_H #define NETHER_FILE_BACKEND_H diff --git a/include/nether_Manager.h b/include/nether_Manager.h index 8e58d56..aa8630e 100644 --- a/include/nether_Manager.h +++ b/include/nether_Manager.h @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2014 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 Manager class implementation for nether + */ + #ifndef NETHER_MANAGER_H #define NETHER_MANAGER_H @@ -19,9 +43,11 @@ class NetherManager : public NetherVerdictListener, public NetherProcessedPacket void packetReceived (const NetherPacket &packet); private: - NetherPolicyBackend *netherPrimaryPolicyBackend, *netherBackupPolicyBackend; - NetherDummyBackend *netherFallbackPolicyBackend; - NetherNetlink *netherNetlink; + void handleSignal(); + const bool handleNetlinkpacket(); + void setupSelectSockets(fd_set &watchedReadDescriptorsSet, fd_set &watchedWriteDescriptorsSet, struct timeval &timeoutSpecification); + std::unique_ptr netherPrimaryPolicyBackend, netherBackupPolicyBackend, netherFallbackPolicyBackend; + std::unique_ptr netherNetlink; NetherConfig netherConfig; int netlinkDescriptor, backendDescriptor, signalDescriptor; sigset_t signalMask; diff --git a/include/nether_Netlink.h b/include/nether_Netlink.h index 8b934a7..eac959c 100644 --- a/include/nether_Netlink.h +++ b/include/nether_Netlink.h @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2014 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 netlink handler class for nether + */ + #ifndef NETHER_NETLINK_H #define NETHER_NETLINK_H diff --git a/include/nether_PolicyBackend.h b/include/nether_PolicyBackend.h index 55879bf..222780c 100644 --- a/include/nether_PolicyBackend.h +++ b/include/nether_PolicyBackend.h @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2014 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 definition of a policy backend class + */ + #ifndef NETHER_POLICY_BACKEND_H #define NETHER_POLICY_BACKEND_H diff --git a/include/nether_Types.h b/include/nether_Types.h index 624abe8..e3ce8c0 100644 --- a/include/nether_Types.h +++ b/include/nether_Types.h @@ -1,3 +1,28 @@ +/* + * Copyright (c) 2014 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 types used in nether + */ + + #ifndef NETHER_TYPES_H #define NETHER_TYPES_H diff --git a/include/nether_Utils.h b/include/nether_Utils.h index 5d654e9..90505a4 100644 --- a/include/nether_Utils.h +++ b/include/nether_Utils.h @@ -1,3 +1,28 @@ +/* + * Copyright (c) 2014 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 + */ + + #ifndef NETHER_UTILS_H #define NETHER_UTILS_H #include "nether_Types.h" diff --git a/nether.cbp b/nether.cbp index aeedfa5..5ee498d 100644 --- a/nether.cbp +++ b/nether.cbp @@ -69,6 +69,10 @@ + + + + @@ -89,6 +93,9 @@ + + + @@ -99,7 +106,6 @@ - diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3585b3d..d6bc873 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,13 +6,13 @@ PKG_CHECK_MODULES (LOGGER libsystemd-journal QUIET) ADD_EXECUTABLE(nether ${NETHER_SOURCES} ${VASUM_LOGGER}) -INCLUDE_DIRECTORIES ( - ../include - ${EXTERNAL_INCLUDE_DIRS} - ${CYNARA_INCLUDE_DIRS} - ${NETFILTER_INCLUDE_DIRS} - ${LOGGER_INCLUDE_DIRS} - ) +INCLUDE_DIRECTORIES(../include + ${EXTERNAL_INCLUDE_DIRS} + ${CYNARA_INCLUDE_DIRS} + ${NETFILTER_INCLUDE_DIRS} + ${LOGGER_INCLUDE_DIRS} +) + if(CYNARA_FOUND) ADD_DEFINITIONS (-DHAVE_CYNARA=${CYNARA_FOUND}) endif() @@ -25,6 +25,7 @@ IF(CMAKE_BUILD_TYPE MATCHES DEBUG) ADD_DEFINITIONS (-D_DEBUG=1) ENDIF(CMAKE_BUILD_TYPE MATCHES DEBUG) -TARGET_LINK_LIBRARIES(nether ${CYNARA_LIBRARIES} - ${NETFILTER_LIBRARIES} - ${LOGGER_LIBRARIES} ) \ No newline at end of file +TARGET_LINK_LIBRARIES(nether ${CYNARA_LIBRARIES} + ${NETFILTER_LIBRARIES} + ${LOGGER_LIBRARIES} +) diff --git a/src/logger/backend-file.cpp b/src/logger/backend-file.cpp index fcfd1bf..f5828e8 100644 --- a/src/logger/backend-file.cpp +++ b/src/logger/backend-file.cpp @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2014 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 File backend for logger + */ + #include "logger/config.hpp" #include "logger/formatter.hpp" #include "logger/backend-file.hpp" @@ -12,11 +36,11 @@ void FileBackend::log(LogLevel logLevel, const std::string& func, const std::string& message) { - std::ofstream out(filePath, std::ios::app); + std::ofstream out(mfilePath, std::ios::app); out << LogFormatter::getHeader(logLevel, file, line, func); out << message; - out << "\n"; + out << std::endl; } -} +} // namespace logger diff --git a/src/logger/backend-journal.cpp b/src/logger/backend-journal.cpp index 85cb46f..af147cd 100644 --- a/src/logger/backend-journal.cpp +++ b/src/logger/backend-journal.cpp @@ -69,4 +69,4 @@ void SystemdJournalBackend::log(LogLevel logLevel, } } // namespace logger -#endif \ No newline at end of file +#endif // HAVE_SYSTEMD_JOURNAL diff --git a/src/logger/backend-syslog.cpp b/src/logger/backend-syslog.cpp index 0542e46..42e8ca0 100644 --- a/src/logger/backend-syslog.cpp +++ b/src/logger/backend-syslog.cpp @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2014 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 Syslog backend for logger + */ + #include "logger/config.hpp" #include "logger/formatter.hpp" #include "logger/backend-syslog.hpp" @@ -39,4 +63,4 @@ void SyslogBackend::log(LogLevel logLevel, syslog(toSyslogPriority(logLevel), "%s %s", LogFormatter::getHeader(logLevel, file, line, func).c_str(), message.c_str()); } -} +} // namespace logger diff --git a/src/nether_CynaraBackend.cpp b/src/nether_CynaraBackend.cpp index 10b426e..e3ec282 100644 --- a/src/nether_CynaraBackend.cpp +++ b/src/nether_CynaraBackend.cpp @@ -1,6 +1,30 @@ +/* + * Copyright (c) 2014 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 Cynara policy backend for nether + */ + #include "nether_CynaraBackend.h" -// #ifdef HAVE_CYNARA +#ifdef HAVE_CYNARA NetherCynaraBackend::NetherCynaraBackend(const NetherConfig &netherConfig) : NetherPolicyBackend(netherConfig), currentCynaraDescriptor(0), @@ -153,4 +177,4 @@ const bool NetherCynaraBackend::processEvents() LOGW("cynara_async_process failed " << cynaraErrorCodeToString(ret)); return (false); } -//#endif +#endif diff --git a/src/nether_FileBackend.cpp b/src/nether_FileBackend.cpp index b73281e..a6c6f81 100644 --- a/src/nether_FileBackend.cpp +++ b/src/nether_FileBackend.cpp @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2014 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 File policy backend for nether + */ + #include "nether_FileBackend.h" NetherFileBackend::NetherFileBackend (const NetherConfig &netherConfig) diff --git a/src/nether_Main.cpp b/src/nether_Main.cpp index 1ab5e9b..08b98fa 100644 --- a/src/nether_Main.cpp +++ b/src/nether_Main.cpp @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2014 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 nether main program + */ + #include "nether_Types.h" #include "nether_Utils.h" #include "nether_Manager.h" @@ -114,6 +138,11 @@ int main(int argc, char *argv[]) case logfileBackend: logger::Logger::setLogBackend (new logger::FileBackend(netherConfig.logBackendArgs)); break; +#if defined(HAVE_SYSTEMD_JOURNAL) + case journalBackend: + logger::Logger::setLogBackend (new logger::SystemdJournalBackend()); + break; +#endif default: logger::Logger::setLogBackend (new logger::StderrBackend(false)); break; diff --git a/src/nether_Manager.cpp b/src/nether_Manager.cpp index 0ec0ae6..5f78bdf 100644 --- a/src/nether_Manager.cpp +++ b/src/nether_Manager.cpp @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2014 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 Manager class implementation for nether + */ + #include "nether_Manager.h" #include "nether_CynaraBackend.h" #include "nether_FileBackend.h" @@ -9,24 +33,20 @@ NetherManager::NetherManager(const NetherConfig &_netherConfig) netherBackupPolicyBackend(nullptr), netherFallbackPolicyBackend(nullptr) { - netherNetlink = new NetherNetlink(netherConfig); + netherNetlink = std::unique_ptr (new NetherNetlink(netherConfig)); netherNetlink->setListener (this); - netherPrimaryPolicyBackend = getPolicyBackend (netherConfig); + netherPrimaryPolicyBackend = std::unique_ptr (getPolicyBackend (netherConfig)); netherPrimaryPolicyBackend->setListener (this); - netherBackupPolicyBackend = getPolicyBackend (netherConfig, false); + netherBackupPolicyBackend = std::unique_ptr (getPolicyBackend (netherConfig, false)); netherBackupPolicyBackend->setListener (this); - netherFallbackPolicyBackend = new NetherDummyBackend(netherConfig); + netherFallbackPolicyBackend = std::unique_ptr (new NetherDummyBackend(netherConfig)); } NetherManager::~NetherManager() { - deleteAndZero (netherPrimaryPolicyBackend); - deleteAndZero (netherBackupPolicyBackend); - deleteAndZero (netherFallbackPolicyBackend); - deleteAndZero (netherNetlink); close (signalDescriptor); } @@ -80,43 +100,13 @@ const bool NetherManager::initialize() } const bool NetherManager::process() -{ - NetherPacket receivedPacket; - int packetReadSize; - ssize_t signalRead; - struct signalfd_siginfo signalfdSignalInfo; +{ fd_set watchedReadDescriptorsSet, watchedWriteDescriptorsSet; struct timeval timeoutSpecification; - char packetBuffer[NETHER_PACKET_BUFFER_SIZE] __attribute__ ((aligned)); - while (1) + for (;;) { - 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() == readOnly) - { - FD_SET(backendDescriptor, &watchedReadDescriptorsSet); - } - else if (netherPrimaryPolicyBackend->getDescriptorStatus() == readWrite) - { - FD_SET(backendDescriptor, &watchedReadDescriptorsSet); - FD_SET(backendDescriptor, &watchedWriteDescriptorsSet); - } - } - - timeoutSpecification.tv_sec = 240; - timeoutSpecification.tv_usec = 0; + setupSelectSockets (watchedReadDescriptorsSet, watchedWriteDescriptorsSet, timeoutSpecification); if (select (FD_SETSIZE, &watchedReadDescriptorsSet, &watchedWriteDescriptorsSet, NULL, &timeoutSpecification) < 0) { @@ -126,60 +116,15 @@ const bool NetherManager::process() if (FD_ISSET(signalDescriptor, &watchedReadDescriptorsSet)) { - LOGD("received signal"); - signalRead = read (signalDescriptor, &signalfdSignalInfo, sizeof(struct signalfd_siginfo)); - - if (signalRead != sizeof(struct signalfd_siginfo)) - { - LOGW("Received incomplete signal information, ignore"); - continue; - } - - 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"); - continue; - } + handleSignal(); } if (FD_ISSET(netlinkDescriptor, &watchedReadDescriptorsSet)) { - LOGD("netlink descriptor active"); - - /* 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)) - { - continue; - } - 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"); - break; - } - } - - if (packetReadSize < 0 && errno == ENOBUFS) - { - LOGI("NetherManager::process losing packets! [bad things might happen]"); - continue; - } - - LOGE("NetherManager::process recv failed " << strerror(errno)); - break; + if (!handleNetlinkpacket()) + break; } else if (FD_ISSET(backendDescriptor, &watchedReadDescriptorsSet) || FD_ISSET(backendDescriptor, &watchedWriteDescriptorsSet)) { - LOGD("policy backend descriptor active"); netherPrimaryPolicyBackend->processEvents(); } else @@ -189,6 +134,96 @@ const bool NetherManager::process() } } +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"); + } +} + +const 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); +} + +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() == readOnly) + { + FD_SET(backendDescriptor, &watchedReadDescriptorsSet); + } + else if (netherPrimaryPolicyBackend->getDescriptorStatus() == readWrite) + { + FD_SET(backendDescriptor, &watchedReadDescriptorsSet); + FD_SET(backendDescriptor, &watchedWriteDescriptorsSet); + } + } + + timeoutSpecification.tv_sec = 240; + timeoutSpecification.tv_usec = 0; +} + NetherConfig &NetherManager::getConfig() { return (netherConfig); diff --git a/src/nether_Netlink.cpp b/src/nether_Netlink.cpp index ed2dd67..2326cab 100644 --- a/src/nether_Netlink.cpp +++ b/src/nether_Netlink.cpp @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2014 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 netlink handler class for nether + */ + #include "nether_Netlink.h" NetherNetlink::NetherNetlink(NetherConfig &netherConfig) diff --git a/src/nether_NetworkUtils.cpp b/src/nether_NetworkUtils.cpp index c6e1072..2d2c4d2 100644 --- a/src/nether_NetworkUtils.cpp +++ b/src/nether_NetworkUtils.cpp @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2014 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 Network utility functions for nether + */ + #include #include #include "nether_Utils.h" @@ -14,9 +38,9 @@ void decodePacket(NetherPacket &packet, unsigned char *payload) { - uint8_t ip_version = (payload[0] >> 4) & 0x0F; + uint8_t ipVersion = (payload[0] >> 4) & 0x0F; - switch(ip_version) + switch(ipVersion) { case 4: packet.protocolType = IPv4; @@ -35,23 +59,23 @@ void decodePacket(NetherPacket &packet, unsigned char *payload) void decodeIPv6Packet(NetherPacket &packet, unsigned char *payload) { - const uint16_t start_of_ip_payload = 40; - uint8_t next_proto; + 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); - next_proto = payload[6]; + nextProto = payload[6]; - switch(next_proto) + switch(nextProto) { case IP_PROTOCOL_UDP: packet.transportType = UDP; - decodeUdp(packet, &payload[start_of_ip_payload]); + decodeUdp(packet, &payload[startOfIpPayload]); break; case IP_PROTOCOL_TCP: packet.transportType = TCP; - decodeTcp(packet, &payload[start_of_ip_payload]); + decodeTcp(packet, &payload[startOfIpPayload]); break; case IP_PROTOCOL_ICMP: packet.transportType = ICMP; @@ -67,24 +91,25 @@ void decodeIPv6Packet(NetherPacket &packet, unsigned char *payload) void decodeIPv4Packet(NetherPacket &packet, unsigned char *payload) { - uint16_t start_of_ip_payload = 0; - uint8_t next_proto; + uint16_t startOfIpPayload = 0; + uint8_t nextProto; - start_of_ip_payload = (payload[0]&0x0F) << 2; + 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); - next_proto = payload[9]; - switch(next_proto) + nextProto = payload[9]; + + switch(nextProto) { case IP_PROTOCOL_UDP: packet.transportType = UDP; - decodeUdp(packet, &payload[start_of_ip_payload]); + decodeUdp(packet, &payload[startOfIpPayload]); break; case IP_PROTOCOL_TCP: packet.transportType = TCP; - decodeTcp(packet, &payload[start_of_ip_payload]); + decodeTcp(packet, &payload[startOfIpPayload]); break; case IP_PROTOCOL_ICMP: packet.transportType = ICMP; -- 2.7.4 From 4daf6b2bcb74a666527dd802dc54d3413914e70e Mon Sep 17 00:00:00 2001 From: RomanKubiak Date: Mon, 20 Jul 2015 16:11:10 +0200 Subject: [PATCH 7/9] Added audit support Updated cmake to include certain constants Made boost optional not required Fixed spec Added iptables-restore support Change-Id: I3b965023bd5c5a07612f80fa2e040454e7db42a2 --- CMakeLists.txt | 33 +++++++++++++++- cmake/Findaudit.cmake | 35 +++++++++++++++++ conf/CMakeLists.txt | 26 ++++++++++++ conf/nether.policy | 29 ++++++++++++++ conf/nether.rules | 41 +++++++++++++++++++ conf/systemd/nether.service.in | 29 ++++++++++++++ config/nether.policy | 7 ---- config/nether.rules | 29 -------------- config/setrules.sh | 85 ---------------------------------------- include/nether_CynaraBackend.h | 8 ++-- include/nether_DummyBackend.h | 23 +++++++++++ include/nether_FileBackend.h | 2 +- include/nether_Manager.h | 15 +++++-- include/nether_Netlink.h | 2 +- include/nether_PolicyBackend.h | 2 +- include/nether_Types.h | 33 +++++++++++++--- include/nether_Utils.h | 2 +- nether.cbp | 12 ++++-- packaging/nether.manifest | 5 --- packaging/nether.spec | 55 +++++++++++++------------- src/CMakeLists.txt | 89 ++++++++++++++++++++++++++++++++---------- src/logger/backend-stderr.cpp | 8 +++- src/logger/level.cpp | 26 +++++++++++- src/nether_CynaraBackend.cpp | 14 +++---- src/nether_FileBackend.cpp | 4 +- src/nether_Main.cpp | 89 +++++++++++++++++++++++++++++++----------- src/nether_Manager.cpp | 70 ++++++++++++++++++++++++++++++++- src/nether_Netlink.cpp | 6 ++- src/nether_NetworkUtils.cpp | 2 +- 29 files changed, 548 insertions(+), 233 deletions(-) create mode 100644 cmake/Findaudit.cmake create mode 100644 conf/CMakeLists.txt create mode 100644 conf/nether.policy create mode 100644 conf/nether.rules create mode 100644 conf/systemd/nether.service.in delete mode 100644 config/nether.policy delete mode 100644 config/nether.rules delete mode 100644 config/setrules.sh delete mode 100644 packaging/nether.manifest diff --git a/CMakeLists.txt b/CMakeLists.txt index d372f16..18fbea1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,34 @@ +# +# 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 +# + CMAKE_MINIMUM_REQUIRED (VERSION 2.6) PROJECT (nether) -INCLUDE(FindPkgConfig) +INCLUDE (FindPkgConfig) SET (CMAKE_CXX_FLAGS "-std=c++11") -ADD_SUBDIRECTORY(src) +SET (CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) + +IF (NOT DEFINED SYSCONF_INSTALL_DIR) + SET(SYSCONF_INSTALL_DIR "/etc") +ENDIF (NOT DEFINED SYSCONF_INSTALL_DIR) + +IF (NOT DEFINED SYSTEMD_UNIT_DIR) + SET(SYSTEMD_UNIT_DIR "${CMAKE_INSTALL_PREFIX}/lib/systemd/system") +ENDIF (NOT DEFINED SYSTEMD_UNIT_DIR) + +ADD_SUBDIRECTORY (src) +ADD_SUBDIRECTORY (conf) diff --git a/cmake/Findaudit.cmake b/cmake/Findaudit.cmake new file mode 100644 index 0000000..f33bb25 --- /dev/null +++ b/cmake/Findaudit.cmake @@ -0,0 +1,35 @@ +# +# 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 +# + +FIND_PATH (AUDIT_INCLUDE_DIR libaudit.h /usr/include /usr/local/include) +FIND_LIBRARY (AUDIT_LIBRARY NAMES libaudit.a PATH /usr/lib /usr/local/lib) + +IF (AUDIT_INCLUDE_DIR AND AUDIT_LIBRARY) + SET (AUDIT_FOUND TRUE) +ENDIF (AUDIT_INCLUDE_DIR AND AUDIT_LIBRARY) + + +IF (AUDIT_FOUND) + IF (NOT audit_FIND_QUIETLY) + MESSAGE(STATUS "Found audit: ${AUDIT_LIBRARY}") + ENDIF (NOT audit_FIND_QUIETLY) +ELSE (AUDIT_FOUND) + IF (audit_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find audit") + ENDIF (audit_FIND_REQUIRED) +ENDIF (AUDIT_FOUND) diff --git a/conf/CMakeLists.txt b/conf/CMakeLists.txt new file mode 100644 index 0000000..be55e51 --- /dev/null +++ b/conf/CMakeLists.txt @@ -0,0 +1,26 @@ +# +# 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 +# + +MESSAGE(STATUS "Installing config files") + +CONFIGURE_FILE(systemd/nether.service.in systemd/nether.service) + +INSTALL(FILES nether.policy DESTINATION ${SYSCONF_INSTALL_DIR}/nether) +INSTALL(FILES nether.rules DESTINATION ${SYSCONF_INSTALL_DIR}/nether) +INSTALL(FILES systemd/nether.service DESTINATION ${SYSTEMD_UNIT_DIR}) +INSTALL(FILES systemd/nether.service DESTINATION ${SYSTEMD_UNIT_DIR}/multi-user.target.wants) diff --git a/conf/nether.policy b/conf/nether.policy new file mode 100644 index 0000000..5161dd3 --- /dev/null +++ b/conf/nether.policy @@ -0,0 +1,29 @@ +# +# 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 +# + +# +# Nether policy +# $UID:$GID:$SECCTX ALLOW|DENY|ALLOW_LOG +# If no match is found for a pcket +# the default verdict is used (can be set via +# command line) +# + +0::_:ALLOW +5002::_:DENY +1354787703::_:ALLOW diff --git a/conf/nether.rules b/conf/nether.rules new file mode 100644 index 0000000..b1ed24c --- /dev/null +++ b/conf/nether.rules @@ -0,0 +1,41 @@ +# +# 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 +# + +# nether iptables rules +*mangle +:PREROUTING ACCEPT [1008811:2134498122] +:INPUT ACCEPT [948545:2129919738] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [816152:74580343] +:POSTROUTING ACCEPT [824147:75308906] +-A OUTPUT -p tcp -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] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [805408:74228055] +:NETHER-ALLOWLOG - [0:0] +:NETHER-DENY - [0:0] +-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 +-A NETHER-DENY -j AUDIT --type reject +-A NETHER-DENY -j REJECT --reject-with icmp-port-unreachable +COMMIT diff --git a/conf/systemd/nether.service.in b/conf/systemd/nether.service.in new file mode 100644 index 0000000..2ccc4fc --- /dev/null +++ b/conf/systemd/nether.service.in @@ -0,0 +1,29 @@ +# +# 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 +# + +[Unit] +Description=nether service + +[Service] +Type=simple +ExecStart=${CMAKE_INSTALL_PREFIX}/bin/nether -d -l JOURNAL -B ${SYSCONF_INSTALL_DIR}/nether/nether.policy -r ${SYSCONF_INSTALL_DIR}/nether/nether.rules +Restart=on-failure +ExecReload=/bin/kill -HUP $MAINPID + +[Install] +WantedBy=multi-user.target diff --git a/config/nether.policy b/config/nether.policy deleted file mode 100644 index 324a7e3..0000000 --- a/config/nether.policy +++ /dev/null @@ -1,7 +0,0 @@ -# Nether policy -# $UID:$GID:$SECCTX ALLOW|DENY|ALLOW_LOG -# - -0::_:ALLOW -5002::_:DENY -1354787703::_:ALLOW \ No newline at end of file diff --git a/config/nether.rules b/config/nether.rules deleted file mode 100644 index 72d4ebe..0000000 --- a/config/nether.rules +++ /dev/null @@ -1,29 +0,0 @@ -# nether iptables rules -*nat -:PREROUTING ACCEPT [214977:18048203] -:INPUT ACCEPT [24506:3910785] -:OUTPUT ACCEPT [46836:3016993] -:POSTROUTING ACCEPT [45527:2930737] -COMMIT -*mangle -:PREROUTING ACCEPT [1008811:2134498122] -:INPUT ACCEPT [948545:2129919738] -:FORWARD ACCEPT [0:0] -:OUTPUT ACCEPT [816152:74580343] -:POSTROUTING ACCEPT [824147:75308906] --A OUTPUT -p tcp -m state --state NEW -m tcp --dport 443 -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] -:FORWARD ACCEPT [0:0] -:OUTPUT ACCEPT [805408:74228055] -:NETHER-ALLOWLOG - [0:0] -:NETHER-DENY - [0:0] --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 --A NETHER-DENY -j AUDIT --type reject --A NETHER-DENY -j REJECT --reject-with icmp-port-unreachable -COMMIT diff --git a/config/setrules.sh b/config/setrules.sh deleted file mode 100644 index 9c2d168..0000000 --- a/config/setrules.sh +++ /dev/null @@ -1,85 +0,0 @@ -# -# Copyright (c) 2014 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 -# -#!/bin/bash -DENY_CHAIN="NETHER-DENY" -ALLOWLOG_CHAIN="NETHER-ALLOWLOG" -TEST_HOST="198.145.20.7" -TEST_PORT=443 -TEST_PROTO="tcp" -TEST_QUEUE=0 -AUDITCTL=auditctl -DENY_MARK="0x3" -ALLOWLOG_MARK="0x4" - -function runcmd { - echo -ne "\t>> $@\n" - $@ -} - -function clean { - echo "Cleanup" - echo - iptables -t mangle -D OUTPUT -m state --state NEW -p $TEST_PROTO -d $TEST_HOST --dport $TEST_PORT -j NFQUEUE --queue-num 0 --queue-bypass 2> /dev/null - iptables -D OUTPUT -m mark --mark $DENY_MARK -j $DENY_CHAIN 2> /dev/null - iptables -D OUTPUT -m mark --mark $ALLOWLOG_MARK -j $ALLOWLOG_CHAIN 2> /dev/null - iptables -F $DENY_CHAIN 2> /dev/null - iptables -F $ALLOWLOG_CHAIN 2> /dev/null - iptables -X $DENY_CHAIN 2> /dev/null - iptables -X $ALLOWLOG_CHAIN 2> /dev/null - echo -} - -function create { - echo "Creating chain" - echo - runcmd iptables -N $DENY_CHAIN - runcmd iptables -N $ALLOWLOG_CHAIN - runcmd iptables -A $DENY_CHAIN -j AUDIT --type REJECT - runcmd iptables -A $DENY_CHAIN -j REJECT - runcmd iptables -A $ALLOWLOG_CHAIN -j AUDIT --type ACCEPT - echo -} - -function create_rules { - echo "Writing rules to output chain $OUTPUT_CHAIN" - echo - runcmd iptables -t mangle -A OUTPUT -m state --state NEW -p $TEST_PROTO -d $TEST_HOST --dport $TEST_PORT -j NFQUEUE --queue-num 0 --queue-bypass - runcmd iptables -A OUTPUT -m mark --mark $DENY_MARK -j $DENY_CHAIN - runcmd iptables -A OUTPUT -m mark --mark $ALLOWLOG_MARK -j $ALLOWLOG_CHAIN - echo -} - -function enable_audit { - if type $AUDITCTL; then - echo -n "Enable audit: " - runcmd $AUDITCTL -e 1 >/dev/null - if [ $? == 0 ]; then - echo "OK" - else - echo "Failed" - fi - else - echo "$AUDITCTL does not exist, can't enable audit" - fi - echo -} - -clean -create -create_rules -enable_audit diff --git a/include/nether_CynaraBackend.h b/include/nether_CynaraBackend.h index a8bc88e..fc21d68 100644 --- a/include/nether_CynaraBackend.h +++ b/include/nether_CynaraBackend.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Roman Kubiak (r.kubiak@samsung.com) * @@ -25,7 +25,7 @@ #ifndef NETHER_CYNARA_BACKEND_H #define NETHER_CYNARA_BACKEND_H -// #ifdef HAVE_CYNARA +#ifdef HAVE_CYNARA #include #include "nether_PolicyBackend.h" @@ -70,5 +70,5 @@ class NetherCynaraBackend : public NetherPolicyBackend int cynaraLastResult; }; -// #endif -#endif +#endif // HAVE_CYNARA +#endif // NETHER_CYNARA_BACKEND_H diff --git a/include/nether_DummyBackend.h b/include/nether_DummyBackend.h index 438e0f7..8bbee85 100644 --- a/include/nether_DummyBackend.h +++ b/include/nether_DummyBackend.h @@ -1,3 +1,26 @@ +/* + * 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 Dummy policy backend + */ #ifndef NETHER_DUMMY_BACKEND_H #define NETHER_DUMMY_BACKEND_H diff --git a/include/nether_FileBackend.h b/include/nether_FileBackend.h index 213b87f..c3cd544 100644 --- a/include/nether_FileBackend.h +++ b/include/nether_FileBackend.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Roman Kubiak (r.kubiak@samsung.com) * diff --git a/include/nether_Manager.h b/include/nether_Manager.h index aa8630e..5407a63 100644 --- a/include/nether_Manager.h +++ b/include/nether_Manager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Roman Kubiak (r.kubiak@samsung.com) * @@ -41,15 +41,24 @@ class NetherManager : public NetherVerdictListener, public NetherProcessedPacket 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(); 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, netherBackupPolicyBackend, netherFallbackPolicyBackend; + std::unique_ptr netherPrimaryPolicyBackend; + std::unique_ptr netherBackupPolicyBackend; + std::unique_ptr netherFallbackPolicyBackend; std::unique_ptr netherNetlink; NetherConfig netherConfig; - int netlinkDescriptor, backendDescriptor, signalDescriptor; + int netlinkDescriptor; + int backendDescriptor; + int signalDescriptor; +#ifdef HAVE_AUDIT + int auditDescriptor; +#endif // HAVE_AUDIT sigset_t signalMask; }; diff --git a/include/nether_Netlink.h b/include/nether_Netlink.h index eac959c..df852e9 100644 --- a/include/nether_Netlink.h +++ b/include/nether_Netlink.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Roman Kubiak (r.kubiak@samsung.com) * diff --git a/include/nether_PolicyBackend.h b/include/nether_PolicyBackend.h index 222780c..dc9ecd6 100644 --- a/include/nether_PolicyBackend.h +++ b/include/nether_PolicyBackend.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Roman Kubiak (r.kubiak@samsung.com) * diff --git a/include/nether_Types.h b/include/nether_Types.h index e3ce8c0..1e67a0b 100644 --- a/include/nether_Types.h +++ b/include/nether_Types.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Roman Kubiak (r.kubiak@samsung.com) * @@ -34,6 +34,8 @@ #include #include +#include +#include #include #include #include @@ -44,19 +46,28 @@ #include #include #include + +#if defined(HAVE_AUDIT) + #include +#endif // HAVE_AUDIT + #include #include "logger/logger.hpp" #include "logger/backend-file.hpp" #include "logger/backend-stderr.hpp" #include "logger/backend-syslog.hpp" -#ifdef HAVE_CYNARA +#if defined(HAVE_SYSTEMD_JOURNAL) + #include "logger/backend-journal.hpp" +#endif // HAVE_SYSTEMD_JOURNAL + +#if defined(HAVE_CYNARA) #define NETHER_PRIMARY_BACKEND cynaraBackend #define NETHER_BACKUP_BACKEND fileBackend #else #define NETHER_PRIMARY_BACKEND fileBackend #define NETHER_BACKUP_BACKEND dummyBackend -#endif +#endif // HAVE_CYNARA #define NETHER_DEFAULT_VERDICT allowAndLog #define NETHER_PACKET_BUFFER_SIZE 4096 @@ -69,6 +80,14 @@ #define NETLINK_DROP_MARK 3 #define NETLINK_ALLOWLOG_MARK 4 #define NETHER_LOG_BACKEND stderrBackend +#define NETHER_IPTABLES_RESTORE_PATH "/usr/sbin/iptables-restore" +#ifndef NETHER_RULES_PATH + #define NETHER_RULES_PATH "/etc/nether/nether.rules" +#endif // NETHER_RULES_PATH + +#ifndef NETHER_POLICY_FILE + #define NETHER_POLICY_FILE "/etc/nether/nether.policy" +#endif // NETHER_POLICY_FILE enum NetherPolicyBackendType { @@ -143,13 +162,17 @@ struct NetherConfig int primaryBackendRetries = 3; int backupBackendRetries = 3; int debugMode = 0; - int nodaemonMode = 0; + int daemonMode = 0; int queueNumber = 0; - std::string backupBackendArgs; + 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; }; class NetherVerdictListener diff --git a/include/nether_Utils.h b/include/nether_Utils.h index 90505a4..8fe6e28 100644 --- a/include/nether_Utils.h +++ b/include/nether_Utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Roman Kubiak (r.kubiak@samsung.com) * diff --git a/nether.cbp b/nether.cbp index 5ee498d..c53b6fc 100644 --- a/nether.cbp +++ b/nether.cbp @@ -20,7 +20,7 @@