Guest User

Untitled

a guest
Jul 18th, 2018
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.60 KB | None | 0 0
  1. [root@web3 Server]# cat ../SSLServer.py
  2. """Bcfg2 SSL server."""
  3.  
  4. __revision__ = '$Revision$'
  5.  
  6. __all__ = [
  7. "SSLServer", "XMLRPCRequestHandler", "XMLRPCServer",
  8. ]
  9.  
  10. import pdb
  11. import pprint
  12. import os
  13. import sys
  14. import xmlrpclib
  15. import socket
  16. import SocketServer
  17. import SimpleXMLRPCServer
  18. import base64
  19. import select
  20. import signal
  21. import logging
  22. import ssl
  23. import threading
  24. import time
  25.  
  26. class ForkedChild(Exception):
  27. pass
  28.  
  29. class XMLRPCDispatcher (SimpleXMLRPCServer.SimpleXMLRPCDispatcher):
  30. logger = logging.getLogger("Cobalt.Server.XMLRPCDispatcher")
  31. def __init__(self, allow_none, encoding):
  32. try:
  33. SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self,
  34. allow_none,
  35. encoding)
  36. except:
  37. # Python 2.4?
  38. SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self)
  39.  
  40. self.allow_none = allow_none
  41. self.encoding = encoding
  42.  
  43. def _marshaled_dispatch(self, address, data):
  44. method_func = None
  45. params, method = xmlrpclib.loads(data)
  46. try:
  47. if '.' not in method:
  48. params = (address, ) + params
  49. response = self.instance._dispatch(method, params, self.funcs)
  50. response = (response, )
  51. raw_response = xmlrpclib.dumps(response, methodresponse=1,
  52. allow_none=self.allow_none,
  53. encoding=self.encoding)
  54. except xmlrpclib.Fault, fault:
  55. raw_response = xmlrpclib.dumps(fault,
  56. allow_none=self.allow_none,
  57. encoding=self.encoding)
  58. except:
  59. self.logger.error("Unexpected handler error", exc_info=1)
  60. # report exception back to server
  61. raw_response = xmlrpclib.dumps(
  62. xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value)),
  63. allow_none=self.allow_none, encoding=self.encoding)
  64. return raw_response
  65.  
  66. class SSLServer (SocketServer.TCPServer, object):
  67.  
  68. """TCP server supporting SSL encryption.
  69.  
  70. Methods:
  71. handshake -- perform a SSL/TLS handshake
  72.  
  73. Properties:
  74. url -- A url pointing to this server.
  75. """
  76.  
  77. allow_reuse_address = True
  78. logger = logging.getLogger("Cobalt.Server.TCPServer")
  79.  
  80. def __init__(self, server_address, RequestHandlerClass, keyfile=None,
  81. certfile=None, reqCert=False, ca=None, timeout=None, protocol='xmlrpc/ssl'):
  82.  
  83. """Initialize the SSL-TCP server.
  84.  
  85. Arguments:
  86. server_address -- address to bind to the server
  87. RequestHandlerClass -- class to handle requests
  88.  
  89. Keyword arguments:
  90. keyfile -- private encryption key filename (enables ssl encryption)
  91. certfile -- certificate file (enables ssl encryption)
  92. reqCert -- client must present certificate
  93. timeout -- timeout for non-blocking request handling
  94. """
  95.  
  96. all_iface_address = ('', server_address[1])
  97. try:
  98. SocketServer.TCPServer.__init__(self, all_iface_address,
  99. RequestHandlerClass)
  100. except socket.error:
  101. self.logger.error("Failed to bind to socket")
  102. raise
  103.  
  104. self.socket.settimeout(timeout)
  105. self.keyfile = keyfile
  106. if keyfile != None:
  107. if keyfile == False or not os.path.exists(keyfile):
  108. self.logger.error("Keyfile %s does not exist" % keyfile)
  109. raise Exception, "keyfile doesn't exist"
  110. self.certfile = certfile
  111. if certfile != None:
  112. if certfile == False or not os.path.exists(certfile):
  113. self.logger.error("Certfile %s does not exist" % certfile)
  114. raise Exception, "certfile doesn't exist"
  115. self.ca = ca
  116. if ca != None:
  117. if ca == False or not os.path.exists(ca):
  118. self.logger.error("CA %s does not exist" % ca)
  119. raise Exception, "ca doesn't exist"
  120. self.reqCert = reqCert
  121. if ca and certfile:
  122. self.mode = ssl.CERT_OPTIONAL
  123. else:
  124. self.mode = ssl.CERT_NONE
  125. if protocol == 'xmlrpc/ssl':
  126. self.ssl_protocol = ssl.PROTOCOL_SSLv23
  127. elif protocol == 'xmlrpc/tlsv1':
  128. self.ssl_protocol = ssl.PROTOCOL_TLSv1
  129. else:
  130. self.logger.error("Unknown protocol %s" % (protocol))
  131. raise Exception, "unknown protocol %s" % protocol
  132.  
  133. def get_request(self):
  134. (sock, sockinfo) = self.socket.accept()
  135. sslsock = ssl.wrap_socket(sock, server_side=True, certfile=self.certfile,
  136. keyfile=self.keyfile, cert_reqs=self.mode,
  137. ca_certs=self.ca, ssl_version=self.ssl_protocol)
  138. return sslsock, sockinfo
  139.  
  140. def _get_url(self):
  141. port = self.socket.getsockname()[1]
  142. hostname = socket.gethostname()
  143. protocol = "https"
  144. return "%s://%s:%i" % (protocol, hostname, port)
  145. url = property(_get_url)
  146.  
  147.  
  148. class XMLRPCRequestHandler (SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
  149.  
  150. """Component XML-RPC request handler.
  151.  
  152. Adds support for HTTP authentication.
  153.  
  154. Exceptions:
  155. CouldNotAuthenticate -- client did not present acceptable authentication information
  156.  
  157. Methods:
  158. authenticate -- prompt a check of a client's provided username and password
  159. handle_one_request -- handle a single rpc (optionally authenticating)
  160. """
  161. logger = logging.getLogger("Cobalt.Server.XMLRPCRequestHandler")
  162.  
  163. def authenticate(self):
  164. print self.headers
  165. try:
  166. header = self.headers['Authorization']
  167. except KeyError:
  168. self.logger.error("No authentication data presented")
  169. return False
  170. auth_type, auth_content = header.split()
  171. auth_content = base64.standard_b64decode(auth_content)
  172. try:
  173. username, password = auth_content.split(":")
  174. except ValueError:
  175. username = auth_content
  176. password = ""
  177. cert = self.request.getpeercert()
  178. client_address = self.request.getpeername()
  179. ret = self.server.instance.authenticate(cert, username,
  180. password, client_address)
  181. self.logger.error("I'm getting here, too.")
  182. return ret
  183.  
  184. def parse_request(self):
  185. """Extends parse_request.
  186.  
  187. Optionally check HTTP authentication when parsing."""
  188. if not SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.parse_request(self):
  189. return False
  190. try:
  191. if not self.authenticate():
  192. self.logger.error("Authentication Failure")
  193. self.send_error(401, self.responses[401][0])
  194. return False
  195. except:
  196. self.logger.error("Unexpected Authentication Failure", exc_info=1)
  197. self.send_error(401, self.responses[401][0])
  198. return False
  199. self.logger.error("Authentication succeeded.")
  200. return True
  201.  
  202. ### need to override do_POST here
  203. def do_POST(self):
  204. try:
  205. max_chunk_size = 10*1024*1024
  206. size_remaining = int(self.headers["content-length"])
  207. L = []
  208. while size_remaining:
  209. chunk_size = min(size_remaining, max_chunk_size)
  210. L.append(self.rfile.read(chunk_size))
  211. size_remaining -= len(L[-1])
  212. data = ''.join(L)
  213. response = self.server._marshaled_dispatch(self.client_address, data)
  214. except:
  215. raise
  216. self.send_response(500)
  217. self.end_headers()
  218. else:
  219. # got a valid XML RPC response
  220. self.send_response(200)
  221. self.send_header("Content-type", "text/xml")
  222. self.send_header("Content-length", str(len(response)))
  223. self.end_headers()
  224. pdb.set_trace()
  225. self.wfile.write(response)
  226. pdb.set_trace()
  227.  
  228. def finish(self):
  229. # shut down the connection
  230. if not self.wfile.closed:
  231. self.wfile.flush()
  232. self.wfile.close()
  233. self.rfile.close()
  234. self.connection.unwrap()
  235.  
  236. class XMLRPCServer (SocketServer.ThreadingMixIn, SSLServer,
  237. XMLRPCDispatcher, object):
  238.  
  239. """Component XMLRPCServer.
  240.  
  241. Methods:
  242. serve_daemon -- serve_forever in a daemonized process
  243. serve_forever -- handle_one_request until not self.serve
  244. shutdown -- stop serve_forever (by setting self.serve = False)
  245. ping -- return all arguments received
  246.  
  247. RPC methods:
  248. ping
  249.  
  250. (additional system.* methods are inherited from base dispatcher)
  251.  
  252. Properties:
  253. require_auth -- the request handler is requiring authorization
  254. credentials -- valid credentials being used for authentication
  255. """
  256.  
  257. def __init__(self, server_address, RequestHandlerClass=None,
  258. keyfile=None, certfile=None, ca=None, protocol='xmlrpc/ssl',
  259. timeout=10,
  260. logRequests=False,
  261. register=True, allow_none=True, encoding=None):
  262.  
  263. """Initialize the XML-RPC server.
  264.  
  265. Arguments:
  266. server_address -- address to bind to the server
  267. RequestHandlerClass -- request handler used by TCP server (optional)
  268.  
  269. Keyword arguments:
  270. keyfile -- private encryption key filename
  271. certfile -- certificate file
  272. logRequests -- log all requests (default False)
  273. register -- presence should be reported to service-location (default True)
  274. allow_none -- allow None values in xml-rpc
  275. encoding -- encoding to use for xml-rpc (default UTF-8)
  276. """
  277.  
  278. XMLRPCDispatcher.__init__(self, allow_none, encoding)
  279.  
  280. if not RequestHandlerClass:
  281. class RequestHandlerClass (XMLRPCRequestHandler):
  282. """A subclassed request handler to prevent class-attribute conflicts."""
  283.  
  284. SSLServer.__init__(self,
  285. server_address, RequestHandlerClass, ca=ca,
  286. timeout=timeout, keyfile=keyfile, certfile=certfile, protocol=protocol)
  287. self.logRequests = logRequests
  288. self.serve = False
  289. self.register = register
  290. self.register_introspection_functions()
  291. self.register_function(self.ping)
  292. self.logger.info("service available at %s" % self.url)
  293. self.timeout = timeout
  294.  
  295. def _tasks_thread(self):
  296. try:
  297. while self.serve:
  298. try:
  299. if self.instance and hasattr(self.instance, 'do_tasks'):
  300. self.instance.do_tasks()
  301. except:
  302. self.logger.error("Unexpected task failure", exc_info=1)
  303. time.sleep(self.timeout)
  304. except:
  305. self.logger.error("tasks_thread failed", exc_info=1)
  306.  
  307. def server_close(self):
  308. SSLServer.server_close(self)
  309. self.logger.info("server_close()")
  310.  
  311. def _get_require_auth(self):
  312. return getattr(self.RequestHandlerClass, "require_auth", False)
  313. def _set_require_auth(self, value):
  314. self.RequestHandlerClass.require_auth = value
  315. require_auth = property(_get_require_auth, _set_require_auth)
  316.  
  317. def _get_credentials(self):
  318. try:
  319. return self.RequestHandlerClass.credentials
  320. except AttributeError:
  321. return dict()
  322. def _set_credentials(self, value):
  323. self.RequestHandlerClass.credentials = value
  324. credentials = property(_get_credentials, _set_credentials)
  325.  
  326. def register_instance(self, instance, *args, **kwargs):
  327. XMLRPCDispatcher.register_instance(self, instance, *args, **kwargs)
  328. try:
  329. name = instance.name
  330. except AttributeError:
  331. name = "unknown"
  332. if hasattr(instance, 'plugins'):
  333. for pname, pinst in instance.plugins.iteritems():
  334. for mname in pinst.__rmi__:
  335. xmname = "%s.%s" % (pname, mname)
  336. fn = getattr(pinst, mname)
  337. self.register_function(fn, name=xmname)
  338. self.logger.info("serving %s at %s" % (name, self.url))
  339.  
  340. def serve_forever(self):
  341. """Serve single requests until (self.serve == False)."""
  342. self.serve = True
  343. self.task_thread = threading.Thread(target=self._tasks_thread)
  344. self.task_thread.start()
  345. self.logger.info("serve_forever() [start]")
  346. signal.signal(signal.SIGINT, self._handle_shutdown_signal)
  347. signal.signal(signal.SIGTERM, self._handle_shutdown_signal)
  348.  
  349. try:
  350. while self.serve:
  351. try:
  352. self.handle_request()
  353. except socket.timeout:
  354. pass
  355. except select.error:
  356. pass
  357. except:
  358. self.logger.error("Got unexpected error in handle_request",
  359. exc_info=1)
  360. finally:
  361. self.logger.info("serve_forever() [stop]")
  362.  
  363. def shutdown(self):
  364. """Signal that automatic service should stop."""
  365. self.serve = False
  366.  
  367. def _handle_shutdown_signal(self, *_):
  368. self.shutdown()
  369.  
  370. def ping(self, *args):
  371. """Echo response."""
  372. self.logger.info("ping(%s)" % (", ".join([repr(arg) for arg in args])))
  373. return args
  374. [root@web3 Server]#
Add Comment
Please, Sign In to add comment