add support for flash clients using flashpolicy
Tony Mack [Wed, 2 Mar 2011 21:26:03 +0000 (16:26 -0500)]
config/default_config.xml
flashpolicy/.sfa_flashpolicy.py.swp [new file with mode: 0644]
flashpolicy/sfa_flashpolicy.py [new file with mode: 0644]
flashpolicy/sfa_flashpolicy_config.xml [new file with mode: 0644]
setup.py
sfa.spec
sfa/init.d/sfa

index aa8a348..3eecf98 100644 (file)
@@ -265,6 +265,31 @@ Thierry Parmentelat
       </variablelist>
     </category>
 
+    <category id="sfa_flashpolicy">
+      <name>SFA Flash Policy</name>
+      <description>The settings that affect the flash policy server that will run
+      as part of this SFA instance.</description>
+
+      <variablelist>
+        <variable id="enabled" type="boolean">
+          <name>Enable Flash Policy Server</name>
+          <value>false</value>
+          <description>Allows this local SFA instance to run a
+          flash policy server.</description>
+        </variable>
+        <variable id="config_file" type="string">
+          <name>Flash policy config file</name>
+          <value>/etc/sfa/sfa_flashpolicy_config.xml</value>
+          <description>The path to where the flash policy config file can be reached.</description>
+        </variable>
+        <variable id="port" type="int">
+          <name>Flash policy port</name>
+          <value>843</value>
+          <description>The flash policy server port.</description>
+        </variable>
+      </variablelist>
+    </category>
+
   </variables>
 
   <comps>
diff --git a/flashpolicy/.sfa_flashpolicy.py.swp b/flashpolicy/.sfa_flashpolicy.py.swp
new file mode 100644 (file)
index 0000000..cf37d73
Binary files /dev/null and b/flashpolicy/.sfa_flashpolicy.py.swp differ
diff --git a/flashpolicy/sfa_flashpolicy.py b/flashpolicy/sfa_flashpolicy.py
new file mode 100644 (file)
index 0000000..8ccdc00
--- /dev/null
@@ -0,0 +1,115 @@
+#!/usr/bin/env python
+#
+# flashpolicyd.py
+# Simple socket policy file server for Flash
+#
+# Usage: flashpolicyd.py [--port=N] --file=FILE
+#
+# Logs to stderr
+# Requires Python 2.5 or later
+
+from __future__ import with_statement
+import os
+import sys
+import optparse
+import socket
+import thread
+import exceptions
+import contextlib
+
+VERSION = 0.1
+
+def daemon():
+    """Daemonize the current process."""
+    if os.fork() != 0: os._exit(0)
+    os.setsid()
+    if os.fork() != 0: os._exit(0)
+    os.umask(0)
+    devnull = os.open(os.devnull, os.O_RDWR)
+    os.dup2(devnull, 0)
+    # xxx fixme - this is just to make sure that nothing gets stupidly lost - should use devnull
+    crashlog = os.open('/var/log/sfa_flashpolicy.log', os.O_RDWR | os.O_APPEND | os.O_CREAT, 0644)
+    os.dup2(crashlog, 1)
+    os.dup2(crashlog, 2)
+
+class policy_server(object):
+    def __init__(self, port, path):
+        self.port = port
+        self.path = path
+        self.policy = self.read_policy(path)
+        self.log('Listening on port %d\n' % port)
+        try:
+            self.sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
+        except AttributeError:
+            # AttributeError catches Python built without IPv6
+            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        except socket.error:
+            # socket.error catches OS with IPv6 disabled
+            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+        self.sock.bind(('', port))
+        self.sock.listen(5)
+    def read_policy(self, path):
+        with file(path, 'rb') as f:
+            policy = f.read(10001)
+            if len(policy) > 10000:
+                raise exceptions.RuntimeError('File probably too large to be a policy file',
+                                              path)
+            if 'cross-domain-policy' not in policy:
+                raise exceptions.RuntimeError('Not a valid policy file',
+                                              path)
+            return policy
+    def run(self):
+        try:
+            while True:
+                thread.start_new_thread(self.handle, self.sock.accept())
+        except socket.error, e:
+            self.log('Error accepting connection: %s' % (e[1],))
+    def handle(self, conn, addr):
+        addrstr = '%s:%s' % (addr[0],addr[1])
+        try:
+            self.log('Connection from %s' % (addrstr,))
+            with contextlib.closing(conn):
+                # It's possible that we won't get the entire request in
+                # a single recv, but very unlikely.
+                request = conn.recv(1024).strip()
+                if request != '<policy-file-request/>\0':
+                    self.log('Unrecognized request from %s: %s' % (addrstr, request))
+                    return
+                self.log('Valid request received from %s' % (addrstr,))
+                conn.sendall(self.policy)
+                self.log('Sent policy file to %s' % (addrstr,))
+        except socket.error, e:
+            self.log('Error handling connection from %s: %s' % (addrstr, e[1]))
+        except Exception, e:
+            self.log('Error handling connection from %s: %s' % (addrstr, e[1]))
+    def log(self, str):
+        print >>sys.stderr, str
+
+def main():
+    parser = optparse.OptionParser(usage = '%prog [--port=PORT] --file=FILE',
+                                   version='%prog ' + str(VERSION))
+    parser.add_option('-p', '--port', dest='port', type=int, default=843,
+                      help='listen on port PORT', metavar='PORT')
+    parser.add_option('-f', '--file', dest='path',
+                      help='server policy file FILE', metavar='FILE')
+    parser.add_option("-d", "--daemon", dest="daemon", action="store_true",
+         help="Run as daemon.", default=False)
+    opts, args = parser.parse_args()
+    if args:
+        parser.error('No arguments are needed. See help.')
+    if not opts.path:
+        parser.error('File must be specified. See help.')
+
+    try:
+        if opts.daemon:
+            daemon()
+        policy_server(opts.port, opts.path).run()
+    except Exception, e:
+        print >> sys.stderr, e
+        sys.exit(1)
+    except KeyboardInterrupt:
+        pass
+
+if __name__ == '__main__':
+    main()
diff --git a/flashpolicy/sfa_flashpolicy_config.xml b/flashpolicy/sfa_flashpolicy_config.xml
new file mode 100644 (file)
index 0000000..757022b
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>\r
+<!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd">\r
+\r
+<cross-domain-policy> \r
+   <site-control permitted-cross-domain-policies="master-only"/>\r
+   <allow-access-from domain="*" to-ports="80,443,12345,12346,12347" />\r
+</cross-domain-policy>\r
+\r
index ffa138e..87a4529 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -31,6 +31,7 @@ bins = [
     'sfa/client/sfiDeleteAttribute.py',
     'sfatables/sfatables',
     'keyconvert/keyconvert.py'
+    'flashpolicy/sfa_flashpolicy.py',
     ]
 
 package_dirs = [
@@ -47,6 +48,7 @@ package_dirs = [
     'sfatables',
     'sfatables/commands',
     'sfatables/processors',
+    'flashpolicy',
     ]
 
 
@@ -60,6 +62,7 @@ data_files = [('/etc/sfa/', [ 'config/aggregates.xml',
                               'sfa/trust/sig.xsd',
                               'sfa/trust/xml.xsd',
                               'sfa/trust/protogeni-rspec-common.xsd',
+                              'flash_policy/flashpolicy_config.xml',
                             ]),
               ('/etc/sfatables/matches/', glob('sfatables/matches/*.xml')),
               ('/etc/sfatables/targets/', glob('sfatables/targets/*.xml')),
index 2736403..94904c3 100644 (file)
--- a/sfa.spec
+++ b/sfa.spec
@@ -70,6 +70,11 @@ Summary: sfatables policy tool for SFA
 Group: Applications/System
 Requires: sfa
 
+%package flashpolicy
+Summary: SFA support for flash clients
+Group: Applications/System
+Requires: sfa
+
 %Package tests
 Summary: unit tests suite for SFA
 Group: Applications/System
@@ -95,6 +100,9 @@ sfatables is a tool for defining access and admission control policies
 in an SFA network, in much the same way as iptables is for ip
 networks. This is the command line interface to manage sfatables
 
+%description flashpolicy
+This package provides support for adobe flash client applications.  
 %description tests
 Provides some binary unit tests in /usr/share/sfa/tests
 
@@ -154,6 +162,10 @@ rm -rf $RPM_BUILD_ROOT
 %files sfatables
 %{_bindir}/sfatables
 
+%files flashpolicy
+%{_bindir}/sfa_flashpolicy.py
+/etc/sfa/flashpolicy_config.xml
+
 %files tests
 %{_datadir}/sfa/tests
 
index 5e579ee..e4b8fec 100755 (executable)
@@ -75,6 +75,10 @@ start() {
         action "SFA SliceMgr" daemon /usr/bin/sfa-server.py -s -d $OPTIONS
     fi
 
+    if [ "$SFA_FLASHPOLICY_ENABLED" -eq 1 ]; then
+        action "Flash Policy Server" daemon /usr/bin/sfa_flashpolicy.py --file="$SFA_FLASHPOLICY_CONFIG_FILE" --port=$SFA_FLASHPOLICY_PORT -d
+    fi
+
     RETVAL=$?
     [ $RETVAL -eq 0 ] && touch /var/lock/subsys/sfa-server.py