CONFIGURE_FILE(systemd/nether.service.in systemd/nether.service)
-INSTALL(FILES nether.policy DESTINATION ${SYSCONF_INSTALL_DIR}/nether)
+INSTALL(FILES file.policy DESTINATION ${SYSCONF_INSTALL_DIR}/nether)
INSTALL(FILES cynara.policy DESTINATION ${SYSCONF_INSTALL_DIR}/nether)
INSTALL(FILES nether.rules DESTINATION ${SYSCONF_INSTALL_DIR}/nether)
INSTALL(FILES systemd/nether.service DESTINATION ${SYSTEMD_UNIT_DIR})
--- /dev/null
+#
+# 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 file policy backend configuration
+# $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
+++ /dev/null
-#
-# 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 file policy backend configuration
-# $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
[Service]
Type=simple
-ExecStart=/usr/local/bin/nether -d -l JOURNAL -B /etc/nether/nether.policy -r /etc/nether/nether.rules
+ExecStart=/usr/local/bin/nether -d -l JOURNAL -P policy=/etc/nether/cynara.policy -B /etc/nether/file.policy -r /etc/nether/nether.rules
Restart=on-failure
ExecReload=/bin/kill -HUP $MAINPID
[Service]
Type=simple
-ExecStart=${CMAKE_INSTALL_PREFIX}/bin/nether -l JOURNAL -B ${SYSCONF_INSTALL_DIR}/nether/nether.policy -r ${SYSCONF_INSTALL_DIR}/nether/nether.rules
+ExecStart=${CMAKE_INSTALL_PREFIX}/bin/nether -l JOURNAL -P policy=${SYSCONF_INSTALL_DIR}/nether/cynara.policy -B ${SYSCONF_INSTALL_DIR}/nether/file.policy -r ${SYSCONF_INSTALL_DIR}/nether/nether.rules
Restart=on-failure
ExecReload=/bin/kill -HUP $MAINPID
* @brief Cynara policy backend for nether
*/
-#ifndef NETHER_CYNARA_BACKEND_H
+#ifndef NETHER_CYNARA_BACKEND_H // NETHER_CYNARA_BACKEND_H
#define NETHER_CYNARA_BACKEND_H
-// #ifdef HAVE_CYNARA
+#ifdef HAVE_CYNARA // HAVE_CYNARA
#include <cynara-client-async.h>
#include "nether_PolicyBackend.h"
+
#include <vector>
-#include <fstream>
#include <map>
#ifndef NETHER_CYNARA_INTERNET_PRIVILEGE
class NetherManager;
const std::string cynaraErrorCodeToString(int cynaraErrorCode);
-typedef std::pair<std::string, u_int32_t> PrivilegePair;
+typedef std::pair<std::string, int32_t> PrivilegePair;
struct NetherCynaraCheckInfo
{
NetherCynaraCheckInfo() {}
- NetherCynaraCheckInfo(NetherPacket _packet, u_int32_t _privilegeId)
+ NetherCynaraCheckInfo(NetherPacket _packet, u_int32_t _privilegeId, cynara_check_id _checkId = -1)
: packet(_packet),
- privilegeId(_privilegeId){}
+ privilegeId(_privilegeId),
+ checkId(_checkId){}
NetherCynaraCheckInfo& operator=(const NetherCynaraCheckInfo &other)
{
packet = other.packet;
privilegeId = other.privilegeId;
-
+ checkId = other.checkId;;
return *this;
}
NetherPacket packet;
u_int32_t privilegeId = -1;
+ cynara_check_id checkId;
};
class NetherCynaraBackend : public NetherPolicyBackend
u_int32_t allPrivilegesToCheck;
};
-// #endif // HAVE_CYNARA
+#endif // HAVE_CYNARA
#endif // NETHER_CYNARA_BACKEND_H
bool reload();
static int callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data);
bool processPacket(char *packetBuffer, const int packetReadSize);
- void setVerdict(const u_int32_t packetId, const NetherVerdict verdict, int mark = -1);
+ void setVerdict(const u_int32_t packetId, const NetherVerdict verdict, int32_t mark = -1);
int getDescriptor();
const NetherConfig &getNetherConfig();
void getInterfaceInfo(struct nfq_data *nfa, NetherPacket &netherPacket);
#endif // NETHER_RULES_PATH
#ifndef NETHER_POLICY_FILE
-#define NETHER_POLICY_FILE "/etc/nether/nether.policy"
+#define NETHER_POLICY_FILE "/etc/nether/file.policy"
#endif // NETHER_POLICY_FILE
uid_t uid;
u_int32_t id;
std::string securityContext;
- int remotePort;
- int localPort;
+ int32_t remotePort = -1;
+ int32_t localPort = -1;
gid_t gid;
pid_t pid;
- char localAddress[NETHER_NETWORK_ADDR_LEN];
- char remoteAddress[NETHER_NETWORK_ADDR_LEN];
+ char localAddress[NETHER_NETWORK_ADDR_LEN] = {0};
+ char remoteAddress[NETHER_NETWORK_ADDR_LEN] = {0};
NetherTransportType transportType;
NetherProtocolType protocolType;
- char outdevName[IFNAMSIZ];
+ char outdevName[IFNAMSIZ] = {0};
};
struct NetherConfig
verdictListener = listenerToSet;
}
- bool castVerdict(const NetherPacket &packet, const NetherVerdict verdict, const int mark = -1)
+ bool castVerdict(const NetherPacket &packet, const NetherVerdict verdict, const int32_t mark = -1)
{
if(verdictListener)
return (verdictListener->verdictCast(packet.id, verdict, mark));
return (false);
}
- bool castVerdict(const u_int32_t packetId, const NetherVerdict verdict, const int mark = -1)
+ bool castVerdict(const u_int32_t packetId, const NetherVerdict verdict, const int32_t mark = -1)
{
if(verdictListener)
return (verdictListener->verdictCast(packetId, verdict, mark));
if(packetListener) packetListener->packetReceived(packetInfoToWrite);
}
- virtual void setVerdict(const u_int32_t packetId, const NetherVerdict verdict, int mark = -1) = 0;
+ virtual void setVerdict(const u_int32_t packetId, const NetherVerdict verdict, const int32_t mark = -1) = 0;
protected:
NetherProcessedPacketListener *packetListener;
%defattr(644,root,root,755)
%caps(cap_sys_admin,cap_mac_override=ei) %attr(755,root,root) %{_bindir}/nether
%dir %{_sysconfdir}/nether
-%config %{_sysconfdir}/nether/nether.policy
+%config %{_sysconfdir}/nether/file.policy
%config %{_sysconfdir}/nether/nether.rules
%config %{_sysconfdir}/nether/cynara.policy
%{_unitdir}/nether.service
)
ADD_DEFINITIONS (-DNETHER_RULES_PATH="${CMAKE_INSTALL_DIR}/etc/nether/nether.rules"
- -DNETHER_POLICY_FILE="${CMAKE_INSTALL_DIR}/etc/nether/nether.policy")
+ -DNETHER_POLICY_FILE="${CMAKE_INSTALL_DIR}/etc/nether/file.policy")
INSTALL (TARGETS nether RUNTIME DESTINATION bin)
#include "nether_CynaraBackend.h"
#include "nether_Utils.h"
+#include <fstream>
+
using namespace std;
-// #ifdef HAVE_CYNARA
+#ifdef HAVE_CYNARA
const std::string cynaraErrorCodeToString(int cynaraErrorCode)
{
cynaraLastResult(CYNARA_API_UNKNOWN_ERROR), cynaraConfig(nullptr),
allPrivilegesToCheck(1) /* if there is no additional policy, only one check is done */
{
+ /* This is the default, if no policy is defined in the file or no
+ privilege name is passed in the command line, the built in
+ or the one defined at build time will be used
+ -1 is the mark that means, ACCEPT (don't mark the packet at all) */
+ privilegeChain.push_back (PrivilegePair (NETHER_CYNARA_INTERNET_PRIVILEGE, -1));
+
if (netherConfig.primaryBackendArgs.length() != 0)
{
parseBackendArgs();
}
- else
- {
- privilegeChain.push_back (PrivilegePair (NETHER_CYNARA_INTERNET_PRIVILEGE, 0));
- }
}
NetherCynaraBackend::~NetherCynaraBackend()
bool NetherCynaraBackend::cynaraCheck(NetherCynaraCheckInfo checkInfo)
{
- cynara_check_id checkId;
-
cynaraLastResult = cynara_async_check_cache(cynaraContext,
checkInfo.packet.securityContext.c_str(),
"",
<< " privilege="
<< privilegeChain[checkInfo.privilegeId].first
<< " mark="
- << privilegeChain[checkInfo.privilegeId].second);
+ << privilegeChain[checkInfo.privilegeId].second
+ << " result string=\""
+ << cynaraErrorCodeToString(cynaraLastResult)
+ << "\""
+ << " packetId="
+ << checkInfo.packet.id);
switch(cynaraLastResult)
{
case CYNARA_API_ACCESS_ALLOWED:
- LOGD(cynaraErrorCodeToString(cynaraLastResult).c_str());
- return (castVerdict(checkInfo.packet, NetherVerdict::allow, privilegeChain[checkInfo.privilegeId].second));
+ return (castVerdict(checkInfo.packet,
+ NetherVerdict::allow,
+ privilegeChain[checkInfo.privilegeId].second));
case CYNARA_API_ACCESS_DENIED:
+ /* We need to copy this into the queue
+ other checks might be needed
+ and this information will be necessary */
+
+ responseQueue[checkInfo.checkId] = checkInfo;
+ return (reEnqueVerdict(checkInfo.checkId));
+
case CYNARA_API_CACHE_MISS:
- LOGD(cynaraErrorCodeToString(cynaraLastResult).c_str());
cynaraLastResult = cynara_async_create_request(cynaraContext,
checkInfo.packet.securityContext.c_str(),
"",
std::to_string(checkInfo.packet.uid).c_str(),
privilegeChain[checkInfo.privilegeId].first.c_str(),
- &checkId,
+ &checkInfo.checkId,
&checkCallback,
this);
if(cynaraLastResult == CYNARA_API_SUCCESS)
{
- responseQueue[checkId] = checkInfo;
-
+ responseQueue[checkInfo.checkId] = checkInfo;
return (true);
}
else
+ {
if(cynaraLastResult == CYNARA_API_SERVICE_NOT_AVAILABLE)
{
LOGW("Cynara offline, fall back to another backend");
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 "<<cynaraErrorCodeToString(cynaraLastResult));
bool NetherCynaraBackend::enqueueVerdict(const NetherPacket &packet)
{
- return (cynaraCheck ( NetherCynaraCheckInfo(packet, 0) ));
+ LOGD("packet id=" << packet.id);
+ return (cynaraCheck (NetherCynaraCheckInfo(packet, 0)));
}
bool NetherCynaraBackend::reEnqueVerdict(cynara_check_id checkId)
{
NetherCynaraCheckInfo checkInfo = responseQueue[checkId];
- /* We goa deny from cynara, we need to check
- if our internal (BAD, SATANIC, EVIL) policy
+ /* We got deny from cynara, we need to check
+ if our internal policy
has other entries and try them too */
if (++checkInfo.privilegeId < allPrivilegesToCheck)
{
+ LOGD("more privileges in policy, keep checking id=" << checkInfo.packet.id);
return (cynaraCheck(checkInfo));
}
else
{
- castVerdict(checkInfo.packet.id, NetherVerdict::deny);
+ LOGD("policy exhausted, deny packet id=" << checkInfo.packet.id);
+ return (castVerdict(checkInfo.packet.id, NetherVerdict::deny));
}
-
- return (true);
}
void NetherCynaraBackend::setCynaraVerdict(cynara_check_id checkId, int cynaraResult)
{
parseInternalPolicy (valueNamePair[1]);
}
+
+ if (valueNamePair[0] == "privname")
+ {
+ privilegeChain.clear();
+ privilegeChain.push_back (PrivilegePair (valueNamePair[1], -1));
+ }
}
}
std::ifstream policyStream (policyFile);
- if (!policyStream.good()) {
- LOGE("Cynara policy file: " << policyFile << " failed to open");
- return false;
+ if (!policyStream.good())
+ {
+ LOGE("Cynara policy file: " << policyFile << " failed to open. Using default privilege: \""
+ << privilegeChain[0].first << "\" for security checks");
+ return (false);
}
std::string s, privname, mark;
mark = s.substr( begin, end - begin );
// Insert the properly extracted (key, value) pair into the map
- std::cout << mark;
+ LOGD("cynara policy add privilege: " << privname << " mark:" << mark);
privilegeChain.push_back(PrivilegePair(privname, std::stoi(mark, 0, 16)));
}
+ /* In case we didn't get at least ONE privilege from the file
+ fall back to default */
+ if (privilegeChain.size() == 0)
+ privilegeChain.push_back (PrivilegePair (NETHER_CYNARA_INTERNET_PRIVILEGE, -1));
+
allPrivilegesToCheck = privilegeChain.size();
return (true);
}
-// #endif
+#endif
else
LOGD("Failed to get security context for packet id=" << packet.id);
- if(nfq_get_payload(nfa, &payload) > 0)
+ if(me->netherConfig.copyPackets && nfq_get_payload(nfa, &payload) > 0)
decodePacket(packet, payload);
me->processNetherPacket(packet); /* this call if from the NetherPacketProcessor class */
return (0);
}
-void NetherNetlink::setVerdict(const u_int32_t packetId, const NetherVerdict verdict, int mark)
+void NetherNetlink::setVerdict(const u_int32_t packetId, const NetherVerdict verdict, int32_t mark)
{
int ret = 0;
LOGD("id=" << packetId << " verdict=" << verdictToString(verdict) << " mark=" << mark);