X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sfa%2Futil%2Fserver.py;h=fadd4cad5b095fae3459ced1e3502a69abe06ac6;hb=3eea82897aba845da0d12c1ba56012e599f58853;hp=0151e5b86c5c1d2386e3f18d909ca4a381e27ebf;hpb=731ec9fdd043e15f1f1da3b4a42f0cb7a941f835;p=sfa.git diff --git a/sfa/util/server.py b/sfa/util/server.py index 0151e5b8..fadd4cad 100644 --- a/sfa/util/server.py +++ b/sfa/util/server.py @@ -6,26 +6,26 @@ # TODO: investigate ways to combine this with existing PLC server? ## -### $Id$ -### $URL$ - import sys +import socket, os import traceback import threading -import socket, os +from Queue import Queue 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.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.util.debug import log 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 @@ -77,7 +77,7 @@ def verify_callback(conn, x509, err, depth, preverify): 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. @@ -107,25 +107,24 @@ class SecureXMLRpcRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): remote_addr = (remote_ip, remote_port) = self.connection.getpeername() self.api.remote_addr = remote_addr response = self.api.handle(remote_addr, request, self.server.method_map) - - except Exception, fault: # This should only happen if the module is buggy # internal error, report as HTTP server error - self.send_response(500) - self.end_headers() - traceback.print_exc() - else: - # got a valid XML RPC response - self.send_response(200) - self.send_header("Content-type", "text/xml") - self.send_header("Content-length", str(len(response))) - self.end_headers() - self.wfile.write(response) - - # shut down the connection - self.wfile.flush() - self.connection.shutdown() # Modified here! + logger.log_exc("server.do_POST") + response = self.api.prepare_response(fault) + #self.send_response(500) + #self.end_headers() + + # got a valid response + self.send_response(200) + self.send_header("Content-type", "text/xml") + self.send_header("Content-length", str(len(response))) + self.end_headers() + self.wfile.write(response) + + # shut down the connection + self.wfile.flush() + self.connection.shutdown() # Modified here! ## # Taken from the web (XXX find reference). Implements an HTTPS xmlrpc server @@ -135,6 +134,7 @@ class SecureXMLRPCServer(BaseHTTPServer.HTTPServer,SimpleXMLRPCServer.SimpleXMLR 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 @@ -153,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') + 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) @@ -167,14 +171,41 @@ class SecureXMLRPCServer(BaseHTTPServer.HTTPServer,SimpleXMLRPCServer.SimpleXMLR # 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 - # (evein in trunk). + # (even in trunk). 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 @@ -247,15 +278,16 @@ class SfaServer(threading.Thread): # @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) + self.server.interface=interface 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 @@ -270,7 +302,6 @@ class SfaServer(threading.Thread): def noop(self, cred, anything): self.decode_authentication(cred) - return anything ##