really fixed the redundant logging issue this time.
[sfa.git] / sfa / util / server.py
index 7de05a5..fadd4ca 100644 (file)
@@ -6,26 +6,26 @@
 # TODO: investigate ways to combine this with existing PLC server?
 ##
 
 # TODO: investigate ways to combine this with existing PLC server?
 ##
 
-### $Id$
-### $URL$
-
 import sys
 import sys
+import socket, os
 import traceback
 import threading
 import traceback
 import threading
-import socket, os
+from Queue import Queue
 import SocketServer
 import BaseHTTPServer
 import SimpleHTTPServer
 import SimpleXMLRPCServer
 from OpenSSL import SSL
 import SocketServer
 import BaseHTTPServer
 import SimpleHTTPServer
 import SimpleXMLRPCServer
 from OpenSSL import SSL
-from Queue import Queue
+
 from sfa.trust.certificate import Keypair, Certificate
 from sfa.trust.certificate import Keypair, Certificate
+from sfa.trust.trustedroot import TrustedRootList
+from sfa.util.config import Config
 from sfa.trust.credential import *
 from sfa.util.faults import *
 from sfa.plc.api import SfaAPI
 from sfa.util.cache import Cache 
 from sfa.trust.credential import *
 from sfa.util.faults import *
 from sfa.plc.api import SfaAPI
 from sfa.util.cache import Cache 
-from sfa.util.debug import log
 from sfa.util.sfalogging import logger
 from sfa.util.sfalogging import logger
+
 ##
 # Verification callback for pyOpenSSL. We do our own checking of keys because
 # we have our own authentication spec. Thus we disable several of the normal
 ##
 # Verification callback for pyOpenSSL. We do our own checking of keys because
 # we have our own authentication spec. Thus we disable several of the normal
@@ -77,7 +77,7 @@ def verify_callback(conn, x509, err, depth, preverify):
     return 0
 
 ##
     return 0
 
 ##
-# taken from the web (XXX find reference). Implents HTTPS xmlrpc request handler
+# taken from the web (XXX find reference). Implements HTTPS xmlrpc request handler
 class SecureXMLRpcRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
     """Secure XML-RPC request handler class.
 
 class SecureXMLRpcRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
     """Secure XML-RPC request handler class.
 
@@ -110,10 +110,10 @@ class SecureXMLRpcRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
         except Exception, fault:
             # This should only happen if the module is buggy
             # internal error, report as HTTP server error
         except Exception, fault:
             # This should only happen if the module is buggy
             # internal error, report as HTTP server error
+            logger.log_exc("server.do_POST")
             response = self.api.prepare_response(fault)
             #self.send_response(500)
             #self.end_headers()
             response = self.api.prepare_response(fault)
             #self.send_response(500)
             #self.end_headers()
-            traceback.print_exc()
        
         # got a valid response
         self.send_response(200)
        
         # got a valid response
         self.send_response(200)
@@ -134,6 +134,7 @@ class SecureXMLRPCServer(BaseHTTPServer.HTTPServer,SimpleXMLRPCServer.SimpleXMLR
 
         It it very similar to SimpleXMLRPCServer but it uses HTTPS for transporting XML data.
         """
 
         It it very similar to SimpleXMLRPCServer but it uses HTTPS for transporting XML data.
         """
+        logger.debug("SecureXMLRPCServer.__init__, server_address=%s, cert_file=%s"%(server_address,cert_file))
         self.logRequests = logRequests
         self.interface = None
         self.key_file = key_file
         self.logRequests = logRequests
         self.interface = None
         self.key_file = key_file
@@ -152,6 +153,10 @@ class SecureXMLRPCServer(BaseHTTPServer.HTTPServer,SimpleXMLRPCServer.SimpleXMLR
         ctx.use_certificate_file(cert_file)
         # If you wanted to verify certs against known CAs.. this is how you would do it
         #ctx.load_verify_locations('/etc/sfa/trusted_roots/plc.gpo.gid')
         ctx.use_certificate_file(cert_file)
         # If you wanted to verify certs against known CAs.. this is how you would do it
         #ctx.load_verify_locations('/etc/sfa/trusted_roots/plc.gpo.gid')
+        config = Config()
+        trusted_cert_files = TrustedRootList(config.get_trustedroots_dir()).get_file_list()
+        for cert_file in trusted_cert_files:
+            ctx.load_verify_locations(cert_file)
         ctx.set_verify(SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback)
         ctx.set_verify_depth(5)
         ctx.set_app_data(self)
         ctx.set_verify(SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback)
         ctx.set_verify_depth(5)
         ctx.set_app_data(self)
@@ -166,14 +171,41 @@ class SecureXMLRPCServer(BaseHTTPServer.HTTPServer,SimpleXMLRPCServer.SimpleXMLR
     # the client.
 
     def _dispatch(self, method, params):
     # the client.
 
     def _dispatch(self, method, params):
+        logger.debug("SecureXMLRPCServer._dispatch, method=%s"%method)
         try:
             return SimpleXMLRPCServer.SimpleXMLRPCDispatcher._dispatch(self, method, params)
         except:
             # can't use format_exc() as it is not available in jython yet
         try:
             return SimpleXMLRPCServer.SimpleXMLRPCDispatcher._dispatch(self, method, params)
         except:
             # can't use format_exc() as it is not available in jython yet
-            # (evein in trunk).
+            # (even in trunk).
             type, value, tb = sys.exc_info()
             raise xmlrpclib.Fault(1,''.join(traceback.format_exception(type, value, tb)))
 
             type, value, tb = sys.exc_info()
             raise xmlrpclib.Fault(1,''.join(traceback.format_exception(type, value, tb)))
 
+    # override this one from the python 2.7 code
+    # originally defined in class TCPServer
+    def shutdown_request(self, request):
+        """Called to shutdown and close an individual request."""
+        # ---------- 
+        # the std python 2.7 code just attempts a request.shutdown(socket.SHUT_WR)
+        # this works fine with regular sockets
+        # However we are dealing with an instance of OpenSSL.SSL.Connection instead
+        # This one only supports shutdown(), and in addition this does not
+        # always perform as expected
+        # ---------- std python 2.7 code
+        try:
+            #explicitly shutdown.  socket.close() merely releases
+            #the socket and waits for GC to perform the actual close.
+            request.shutdown(socket.SHUT_WR)
+        except socket.error:
+            pass #some platforms may raise ENOTCONN here
+        # ----------
+        except TypeError:
+            # we are dealing with an OpenSSL.Connection object, 
+            # try to shut it down but never mind if that fails
+            try: request.shutdown()
+            except: pass
+        # ----------
+        self.close_request(request)
+
 ## From Active State code: http://code.activestate.com/recipes/574454/
 # This is intended as a drop-in replacement for the ThreadingMixIn class in 
 # module SocketServer of the standard lib. Instead of spawning a new thread 
 ## From Active State code: http://code.activestate.com/recipes/574454/
 # This is intended as a drop-in replacement for the ThreadingMixIn class in 
 # module SocketServer of the standard lib. Instead of spawning a new thread 
@@ -246,15 +278,16 @@ class SfaServer(threading.Thread):
     # @param cert_file certificate filename containing public key 
     #   (could be a GID file)
 
     # @param cert_file certificate filename containing public key 
     #   (could be a GID file)
 
-    def __init__(self, ip, port, key_file, cert_file):
+    def __init__(self, ip, port, key_file, cert_file,interface):
         threading.Thread.__init__(self)
         self.key = Keypair(filename = key_file)
         self.cert = Certificate(filename = cert_file)
         #self.server = SecureXMLRPCServer((ip, port), SecureXMLRpcRequestHandler, key_file, cert_file)
         self.server = ThreadedServer((ip, port), SecureXMLRpcRequestHandler, key_file, cert_file)
         threading.Thread.__init__(self)
         self.key = Keypair(filename = key_file)
         self.cert = Certificate(filename = cert_file)
         #self.server = SecureXMLRPCServer((ip, port), SecureXMLRpcRequestHandler, key_file, cert_file)
         self.server = ThreadedServer((ip, port), SecureXMLRpcRequestHandler, key_file, cert_file)
+        self.server.interface=interface
         self.trusted_cert_list = None
         self.register_functions()
         self.trusted_cert_list = None
         self.register_functions()
-
+        logger.info("Starting SfaServer, interface=%s"%interface)
 
     ##
     # Register functions that will be served by the XMLRPC server. This
 
     ##
     # Register functions that will be served by the XMLRPC server. This