# 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
-#import sfa.util.sfalogging
from sfa.trust.certificate import Keypair, Certificate
+from sfa.trust.trustedroots import TrustedRoots
+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
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.
except Exception, fault:
# This should only happen if the module is buggy
# internal error, report as HTTP server error
- traceback.print_exc()
+ logger.log_exc("server.do_POST")
response = self.api.prepare_response(fault)
#self.send_response(500)
#self.end_headers()
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
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 = TrustedRoots(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)
# 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
# @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