3818d30ae206148723dc6951b11cc9a67c697b9b
[AGL/meta-agl.git] / meta-security / recipes-security / smacknet / files / smacknet
1 #!/usr/bin/python
2 # Copyright (c) 2012, 2013, Intel Corporation 
3 # Copyright (c) 2009 David Wolinsky <davidiw@ufl.edu), University of Florida
4 # All rights reserved.
5
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 #    notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 #    notice, this list of conditions and the following disclaimer in the
13 #    documentation and/or other materials provided with the distribution.
14 # 3. The name of the author may not be used to endorse or promote products
15 #    derived from this software without specific prior written permission.
16 #
17 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 import socket,fcntl, struct, thread
29 import os.path
30 import sys
31
32 SMACKFS_LOAD="/sys/fs/smackfs/load2"
33 SMACKFS_NETLABEL="/sys/fs/smackfs/netlabel"
34 SIOCGIFADDR = 0x8915
35 SIOCGIFNETMASK = 0x891b
36
37 def get_ip_address(ifname):
38     s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
39     return fcntl.ioctl(s.fileno(), SIOCGIFADDR, 
40                         struct.pack('256s', ifname.encode("utf-8")))[20:24]
41
42 def get_netmask(ifname):
43    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
44    return fcntl.ioctl(s.fileno(), SIOCGIFNETMASK, 
45                         struct.pack('256s', ifname.encode("utf-8")))[20:24]
46
47 def applynetlabeltags(interface, addr):
48         if not interface.startswith("lo"):
49                 bmask = get_netmask(interface.encode("utf-8"))
50                 prefix = bin(struct.unpack(">L", bmask)[0]).count("1")
51                 tags = [
52                         addr+"/"+str(prefix)+" Network::Local\n", 
53                         "0.0.0.0/0 Network::Cloud\n",
54                         "127.0.0.1/8 -CIPSO\n"]
55                 smackfs_netlabel(tags)
56         
57 def loadnetlabelrules():
58         rulesSystem = [
59                 "System Network::Cloud w\n",
60                 "System Network::Local w\n",
61                 "Network::Cloud System w\n",
62                 "Network::Local System w\n"]
63         smackfs_load2(rulesSystem)
64
65 def smackfs_load2 (rules):
66         with open(SMACKFS_LOAD, "w") as load2:
67                 for rule in rules:
68                         load2.write(rule)
69
70 def smackfs_netlabel (tags):
71         for tag in tags:
72                 with open(SMACKFS_NETLABEL, "w") as netlabel:
73                         netlabel.write(tag)
74
75 """ 
76     Source of: Class ip monitor, and other functions named bellow.
77     Original author: David Wolinsky <davidiw@ufl.edu
78     Copied from: https://github.com/davidiw/Grid-Appliance/blob/master/scripts/ip_monitor.py
79     
80 """
81
82 """4 byte alignment"""
83
84 def align(inc):
85         diff = inc % 4
86         return inc + ((4 - diff) % 4)
87
88 class ifaddr:
89   """Parse an ifaddr packet"""
90   LOCAL = 2
91   LABEL = 3
92
93   def __init__(self, packet):
94     self.family, self.prefixlen, self.flags, self.scope, self.index = \
95         struct.unpack("BBBBI", packet[:8])
96
97 class rtattr:
98   """Parse a rtattr packet"""
99   GRP_IPV4_IFADDR = 0x10
100
101   NEWADDR = 20
102   DELADDR = 21
103   GETADDR = 22
104
105   def __init__(self, packet):
106     self.len, self.type = struct.unpack("HH", packet[:4])
107     if self.type == ifaddr.LOCAL:
108       addr = struct.unpack("BBBB", packet[4:self.len])
109       self.payload = "%s.%s.%s.%s" % (addr[0], addr[1], addr[2], addr[3])
110     elif self.type == ifaddr.LABEL:
111       self.payload = packet[4:self.len].strip("\0")
112     else:
113       self.payload = packet[4:self.len]
114
115 class netlink:
116   """Parse a netlink packet"""
117   REQUEST = 1
118   ROOT = 0x100
119   MATCH = 0x200
120   DONE = 3
121
122   def __init__(self, packet):
123     self.msglen, self.msgtype, self.flags, self.seq, self.pid = \
124         struct.unpack("IHHII", packet[:16])
125     self.ifa = None
126     try:
127       self.ifa = ifaddr(packet[16:24])
128     except:
129       return
130
131     self.rtas = {}
132     pos = 24
133     while pos < self.msglen:
134       try:
135         rta = rtattr(packet[pos:])
136       except:
137         break
138       pos += align(rta.len)
139       self.rtas[rta.type] = rta.payload
140
141 class ip_monitor:
142   def __init__(self, callback = None):
143     if callback == None:
144       callback = self.print_cb
145     self._callback = callback
146
147   def print_cb(self, label, addr):
148     print (label + " => " + addr)
149
150   def request_addrs(self, sock):
151     sock.send(struct.pack("IHHIIBBBBI", 24, rtattr.GETADDR, \
152       netlink.REQUEST | netlink.ROOT | netlink.MATCH, 0, sock.getsockname()[0], \
153       socket.AF_INET, 0, 0, 0, 0))
154
155   def start_thread(self):
156     thread.start_new_thread(self.run, ())
157
158   def run(self):
159     sock = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, socket.NETLINK_ROUTE)
160     sock.bind((0, rtattr.GRP_IPV4_IFADDR))
161     self.request_addrs(sock)
162
163     while True:
164       data = sock.recv(4096)
165       pos = 0
166       while pos < len(data):
167         nl = netlink(data[pos:])
168         if nl.msgtype == netlink.DONE:
169           break
170         pos += align(nl.msglen)
171         if nl.msgtype != rtattr.NEWADDR:
172           continue
173         self._callback(nl.rtas[ifaddr.LABEL], nl.rtas[ifaddr.LOCAL])
174
175 def main():
176         if not os.path.isfile(SMACKFS_LOAD):
177                 print ("Smack not found.")
178                 return -1
179         loadnetlabelrules()
180         
181         ip_monitor(applynetlabeltags).run()
182
183 if __name__ == "__main__":
184     main()