4 # Simple socket policy file server for Flash
6 # Usage: flashpolicyd.py [--port=N] --file=FILE
9 # Requires Python 2.5 or later
11 from __future__ import with_statement
23 """Daemonize the current process."""
24 if os.fork() != 0: os._exit(0)
26 if os.fork() != 0: os._exit(0)
28 devnull = os.open(os.devnull, os.O_RDWR)
30 # xxx fixme - this is just to make sure that nothing gets stupidly lost - should use devnull
31 crashlog = os.open('/var/log/sfa_flashpolicy.log', os.O_RDWR | os.O_APPEND | os.O_CREAT, 0644)
35 class policy_server(object):
36 def __init__(self, port, path):
39 self.policy = self.read_policy(path)
40 self.log('Listening on port %d\n' % port)
42 self.sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
43 except AttributeError:
44 # AttributeError catches Python built without IPv6
45 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
47 # socket.error catches OS with IPv6 disabled
48 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
49 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
50 self.sock.bind(('', port))
52 def read_policy(self, path):
53 with file(path, 'rb') as f:
54 policy = f.read(10001)
55 if len(policy) > 10000:
56 raise exceptions.RuntimeError('File probably too large to be a policy file',
58 if 'cross-domain-policy' not in policy:
59 raise exceptions.RuntimeError('Not a valid policy file',
65 thread.start_new_thread(self.handle, self.sock.accept())
66 except socket.error, e:
67 self.log('Error accepting connection: %s' % (e[1],))
68 def handle(self, conn, addr):
69 addrstr = '%s:%s' % (addr[0],addr[1])
71 self.log('Connection from %s' % (addrstr,))
72 with contextlib.closing(conn):
73 # It's possible that we won't get the entire request in
74 # a single recv, but very unlikely.
75 request = conn.recv(1024).strip()
76 #if request != '<policy-file-request/>\0':
77 # self.log('Unrecognized request from %s: %s' % (addrstr, request))
79 self.log('Valid request received from %s' % (addrstr,))
80 conn.sendall(self.policy)
81 self.log('Sent policy file to %s' % (addrstr,))
82 except socket.error, e:
83 self.log('Error handling connection from %s: %s' % (addrstr, e[1]))
85 self.log('Error handling connection from %s: %s' % (addrstr, e[1]))
87 print >>sys.stderr, str
90 parser = optparse.OptionParser(usage = '%prog [--port=PORT] --file=FILE',
91 version='%prog ' + str(VERSION))
92 parser.add_option('-p', '--port', dest='port', type=int, default=843,
93 help='listen on port PORT', metavar='PORT')
94 parser.add_option('-f', '--file', dest='path',
95 help='server policy file FILE', metavar='FILE')
96 parser.add_option("-d", "--daemon", dest="daemon", action="store_true",
97 help="Run as daemon.", default=False)
98 opts, args = parser.parse_args()
100 parser.error('No arguments are needed. See help.')
102 parser.error('File must be specified. See help.')
107 policy_server(opts.port, opts.path).run()
109 print >> sys.stderr, e
111 except KeyboardInterrupt:
114 if __name__ == '__main__':