Integrate parts of meta-intel-iot-security
[AGL/meta-agl.git] / meta-security / recipes-security / smacknet / files / smacknet
diff --git a/meta-security/recipes-security/smacknet/files/smacknet b/meta-security/recipes-security/smacknet/files/smacknet
new file mode 100644 (file)
index 0000000..3818d30
--- /dev/null
@@ -0,0 +1,184 @@
+#!/usr/bin/python
+# Copyright (c) 2012, 2013, Intel Corporation 
+# Copyright (c) 2009 David Wolinsky <davidiw@ufl.edu), University of Florida
+# All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+#    derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import socket,fcntl, struct, thread
+import os.path
+import sys
+
+SMACKFS_LOAD="/sys/fs/smackfs/load2"
+SMACKFS_NETLABEL="/sys/fs/smackfs/netlabel"
+SIOCGIFADDR = 0x8915
+SIOCGIFNETMASK = 0x891b
+
+def get_ip_address(ifname):
+    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+    return fcntl.ioctl(s.fileno(), SIOCGIFADDR, 
+                       struct.pack('256s', ifname.encode("utf-8")))[20:24]
+
+def get_netmask(ifname):
+   s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+   return fcntl.ioctl(s.fileno(), SIOCGIFNETMASK, 
+                       struct.pack('256s', ifname.encode("utf-8")))[20:24]
+
+def applynetlabeltags(interface, addr):
+       if not interface.startswith("lo"):
+               bmask = get_netmask(interface.encode("utf-8"))
+               prefix = bin(struct.unpack(">L", bmask)[0]).count("1")
+               tags = [
+                       addr+"/"+str(prefix)+" Network::Local\n", 
+                       "0.0.0.0/0 Network::Cloud\n",
+                       "127.0.0.1/8 -CIPSO\n"]
+               smackfs_netlabel(tags)
+       
+def loadnetlabelrules():
+       rulesSystem = [
+               "System Network::Cloud w\n",
+               "System Network::Local w\n",
+               "Network::Cloud System w\n",
+               "Network::Local System w\n"]
+       smackfs_load2(rulesSystem)
+
+def smackfs_load2 (rules):
+       with open(SMACKFS_LOAD, "w") as load2:
+               for rule in rules:
+                       load2.write(rule)
+
+def smackfs_netlabel (tags):
+       for tag in tags:
+               with open(SMACKFS_NETLABEL, "w") as netlabel:
+                       netlabel.write(tag)
+
+""" 
+    Source of: Class ip monitor, and other functions named bellow.
+    Original author: David Wolinsky <davidiw@ufl.edu
+    Copied from: https://github.com/davidiw/Grid-Appliance/blob/master/scripts/ip_monitor.py
+    
+"""
+
+"""4 byte alignment"""
+
+def align(inc):
+       diff = inc % 4
+       return inc + ((4 - diff) % 4)
+
+class ifaddr:
+  """Parse an ifaddr packet"""
+  LOCAL = 2
+  LABEL = 3
+
+  def __init__(self, packet):
+    self.family, self.prefixlen, self.flags, self.scope, self.index = \
+        struct.unpack("BBBBI", packet[:8])
+
+class rtattr:
+  """Parse a rtattr packet"""
+  GRP_IPV4_IFADDR = 0x10
+
+  NEWADDR = 20
+  DELADDR = 21
+  GETADDR = 22
+
+  def __init__(self, packet):
+    self.len, self.type = struct.unpack("HH", packet[:4])
+    if self.type == ifaddr.LOCAL:
+      addr = struct.unpack("BBBB", packet[4:self.len])
+      self.payload = "%s.%s.%s.%s" % (addr[0], addr[1], addr[2], addr[3])
+    elif self.type == ifaddr.LABEL:
+      self.payload = packet[4:self.len].strip("\0")
+    else:
+      self.payload = packet[4:self.len]
+
+class netlink:
+  """Parse a netlink packet"""
+  REQUEST = 1
+  ROOT = 0x100
+  MATCH = 0x200
+  DONE = 3
+
+  def __init__(self, packet):
+    self.msglen, self.msgtype, self.flags, self.seq, self.pid = \
+        struct.unpack("IHHII", packet[:16])
+    self.ifa = None
+    try:
+      self.ifa = ifaddr(packet[16:24])
+    except:
+      return
+
+    self.rtas = {}
+    pos = 24
+    while pos < self.msglen:
+      try:
+        rta = rtattr(packet[pos:])
+      except:
+        break
+      pos += align(rta.len)
+      self.rtas[rta.type] = rta.payload
+
+class ip_monitor:
+  def __init__(self, callback = None):
+    if callback == None:
+      callback = self.print_cb
+    self._callback = callback
+
+  def print_cb(self, label, addr):
+    print (label + " => " + addr)
+
+  def request_addrs(self, sock):
+    sock.send(struct.pack("IHHIIBBBBI", 24, rtattr.GETADDR, \
+      netlink.REQUEST | netlink.ROOT | netlink.MATCH, 0, sock.getsockname()[0], \
+      socket.AF_INET, 0, 0, 0, 0))
+
+  def start_thread(self):
+    thread.start_new_thread(self.run, ())
+
+  def run(self):
+    sock = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, socket.NETLINK_ROUTE)
+    sock.bind((0, rtattr.GRP_IPV4_IFADDR))
+    self.request_addrs(sock)
+
+    while True:
+      data = sock.recv(4096)
+      pos = 0
+      while pos < len(data):
+        nl = netlink(data[pos:])
+        if nl.msgtype == netlink.DONE:
+          break
+        pos += align(nl.msglen)
+        if nl.msgtype != rtattr.NEWADDR:
+          continue
+        self._callback(nl.rtas[ifaddr.LABEL], nl.rtas[ifaddr.LOCAL])
+
+def main():
+       if not os.path.isfile(SMACKFS_LOAD):
+               print ("Smack not found.")
+               return -1
+       loadnetlabelrules()
+       
+       ip_monitor(applynetlabeltags).run()
+
+if __name__ == "__main__":
+    main()