ssl_context_util.py 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. """ndg_httpsclient SSL Context utilities module containing convenience routines
  2. for setting SSL context configuration.
  3. """
  4. __author__ = "P J Kershaw (STFC)"
  5. __date__ = "09/12/11"
  6. __copyright__ = "(C) 2012 Science and Technology Facilities Council"
  7. __license__ = "BSD - see LICENSE file in top-level directory"
  8. __contact__ = "Philip.Kershaw@stfc.ac.uk"
  9. __revision__ = '$Id$'
  10. import urlparse
  11. from OpenSSL import SSL
  12. from ndg.httpsclient.ssl_peer_verification import ServerSSLCertVerification
  13. class SSlContextConfig(object):
  14. """
  15. Holds configuration options for creating a SSL context. This is used as a
  16. template to create the contexts with specific verification callbacks.
  17. """
  18. def __init__(self, key_file=None, cert_file=None, pem_file=None, ca_dir=None,
  19. verify_peer=False):
  20. self.key_file = key_file
  21. self.cert_file = cert_file
  22. self.pem_file = pem_file
  23. self.ca_dir = ca_dir
  24. self.verify_peer = verify_peer
  25. def make_ssl_context_from_config(ssl_config=False, url=None):
  26. return make_ssl_context(ssl_config.key_file, ssl_config.cert_file,
  27. ssl_config.pem_file, ssl_config.ca_dir,
  28. ssl_config.verify_peer, url)
  29. def make_ssl_context(key_file=None, cert_file=None, pem_file=None, ca_dir=None,
  30. verify_peer=False, url=None, method=SSL.SSLv23_METHOD,
  31. key_file_passphrase=None):
  32. """
  33. Creates SSL context containing certificate and key file locations.
  34. """
  35. ssl_context = SSL.Context(method)
  36. # Key file defaults to certificate file if present.
  37. if cert_file:
  38. ssl_context.use_certificate_file(cert_file)
  39. if key_file_passphrase:
  40. passwd_cb = lambda max_passphrase_len, set_prompt, userdata: \
  41. key_file_passphrase
  42. ssl_context.set_passwd_cb(passwd_cb)
  43. if key_file:
  44. ssl_context.use_privatekey_file(key_file)
  45. elif cert_file:
  46. ssl_context.use_privatekey_file(cert_file)
  47. if pem_file or ca_dir:
  48. ssl_context.load_verify_locations(pem_file, ca_dir)
  49. def _callback(conn, x509, errnum, errdepth, preverify_ok):
  50. """Default certification verification callback.
  51. Performs no checks and returns the status passed in.
  52. """
  53. return preverify_ok
  54. verify_callback = _callback
  55. if verify_peer:
  56. ssl_context.set_verify_depth(9)
  57. if url:
  58. set_peer_verification_for_url_hostname(ssl_context, url)
  59. else:
  60. ssl_context.set_verify(SSL.VERIFY_PEER, verify_callback)
  61. else:
  62. ssl_context.set_verify(SSL.VERIFY_NONE, verify_callback)
  63. return ssl_context
  64. def set_peer_verification_for_url_hostname(ssl_context, url,
  65. if_verify_enabled=False):
  66. '''Convenience routine to set peer verification callback based on
  67. ServerSSLCertVerification class'''
  68. if not if_verify_enabled or (ssl_context.get_verify_mode() & SSL.VERIFY_PEER):
  69. urlObj = urlparse.urlparse(url)
  70. hostname = urlObj.hostname
  71. verify_callback = ServerSSLCertVerification(hostname=hostname)
  72. ssl_context.set_verify(SSL.VERIFY_PEER, verify_callback)