Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ssl.py 8.4KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. # -*- test-case-name: twisted.test.test_ssl -*-
  2. # Copyright (c) Twisted Matrix Laboratories.
  3. # See LICENSE for details.
  4. """
  5. This module implements Transport Layer Security (TLS) support for Twisted. It
  6. requires U{PyOpenSSL <https://pypi.python.org/pypi/pyOpenSSL>}.
  7. If you wish to establish a TLS connection, please use one of the following
  8. APIs:
  9. - SSL endpoints for L{servers
  10. <twisted.internet.endpoints.SSL4ServerEndpoint>} and L{clients
  11. <twisted.internet.endpoints.SSL4ClientEndpoint>}
  12. - L{startTLS <twisted.internet.interfaces.ITLSTransport.startTLS>}
  13. - L{connectSSL <twisted.internet.interfaces.IReactorSSL.connectSSL>}
  14. - L{listenSSL <twisted.internet.interfaces.IReactorSSL.listenSSL>}
  15. These APIs all require a C{contextFactory} argument that specifies their
  16. security properties, such as certificate, private key, certificate authorities
  17. to verify the peer, allowed TLS protocol versions, cipher suites, and so on.
  18. The recommended value for this argument is a L{CertificateOptions} instance;
  19. see its documentation for an explanation of the available options.
  20. The C{contextFactory} name is a bit of an anachronism now, as context factories
  21. have been replaced with "connection creators", but these objects serve the same
  22. role.
  23. Be warned that implementing your own connection creator (i.e.: value for the
  24. C{contextFactory}) is both difficult and dangerous; the Twisted team has worked
  25. hard to make L{CertificateOptions}' API comprehensible and unsurprising, and
  26. the Twisted team is actively maintaining it to ensure that it becomes more
  27. secure over time.
  28. If you are really absolutely sure that you want to take on the risk of
  29. implementing your own connection creator based on the pyOpenSSL API, see the
  30. L{server connection creator
  31. <twisted.internet.interfaces.IOpenSSLServerConnectionCreator>} and L{client
  32. connection creator
  33. <twisted.internet.interfaces.IOpenSSLServerConnectionCreator>} interfaces.
  34. Developers using Twisted, please ignore the L{Port}, L{Connector}, and
  35. L{Client} classes defined here, as these are details of certain reactors' TLS
  36. implementations, exposed by accident (and remaining here only for compatibility
  37. reasons). If you wish to establish a TLS connection, please use one of the
  38. APIs listed above.
  39. @note: "SSL" (Secure Sockets Layer) is an antiquated synonym for "TLS"
  40. (Transport Layer Security). You may see these terms used interchangeably
  41. throughout the documentation.
  42. """
  43. from zope.interface import implementedBy, implementer, implementer_only
  44. # System imports
  45. from OpenSSL import SSL
  46. # Twisted imports
  47. from twisted.internet import interfaces, tcp
  48. supported = True
  49. @implementer(interfaces.IOpenSSLContextFactory)
  50. class ContextFactory:
  51. """A factory for SSL context objects, for server SSL connections."""
  52. isClient = 0
  53. def getContext(self):
  54. """Return a SSL.Context object. override in subclasses."""
  55. raise NotImplementedError
  56. class DefaultOpenSSLContextFactory(ContextFactory):
  57. """
  58. L{DefaultOpenSSLContextFactory} is a factory for server-side SSL context
  59. objects. These objects define certain parameters related to SSL
  60. handshakes and the subsequent connection.
  61. @ivar _contextFactory: A callable which will be used to create new
  62. context objects. This is typically L{OpenSSL.SSL.Context}.
  63. """
  64. _context = None
  65. def __init__(
  66. self,
  67. privateKeyFileName,
  68. certificateFileName,
  69. sslmethod=SSL.TLS_METHOD,
  70. _contextFactory=SSL.Context,
  71. ):
  72. """
  73. @param privateKeyFileName: Name of a file containing a private key
  74. @param certificateFileName: Name of a file containing a certificate
  75. @param sslmethod: The SSL method to use
  76. """
  77. self.privateKeyFileName = privateKeyFileName
  78. self.certificateFileName = certificateFileName
  79. self.sslmethod = sslmethod
  80. self._contextFactory = _contextFactory
  81. # Create a context object right now. This is to force validation of
  82. # the given parameters so that errors are detected earlier rather
  83. # than later.
  84. self.cacheContext()
  85. def cacheContext(self):
  86. if self._context is None:
  87. ctx = self._contextFactory(self.sslmethod)
  88. # Disallow SSLv2! It's insecure! SSLv3 has been around since
  89. # 1996. It's time to move on.
  90. ctx.set_options(SSL.OP_NO_SSLv2)
  91. ctx.use_certificate_file(self.certificateFileName)
  92. ctx.use_privatekey_file(self.privateKeyFileName)
  93. self._context = ctx
  94. def __getstate__(self):
  95. d = self.__dict__.copy()
  96. del d["_context"]
  97. return d
  98. def __setstate__(self, state):
  99. self.__dict__ = state
  100. def getContext(self):
  101. """
  102. Return an SSL context.
  103. """
  104. return self._context
  105. @implementer(interfaces.IOpenSSLContextFactory)
  106. class ClientContextFactory:
  107. """A context factory for SSL clients."""
  108. isClient = 1
  109. # TLS_METHOD allows negotiation of multiple TLS versions.
  110. method = SSL.TLS_METHOD
  111. _contextFactory = SSL.Context
  112. def getContext(self):
  113. ctx = self._contextFactory(self.method)
  114. ctx.set_options(
  115. SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3 | SSL.OP_NO_TLSv1 | SSL.OP_NO_TLSv1_1
  116. )
  117. return ctx
  118. @implementer_only(
  119. interfaces.ISSLTransport,
  120. *(i for i in implementedBy(tcp.Client) if i != interfaces.ITLSTransport),
  121. )
  122. class Client(tcp.Client):
  123. """
  124. I am an SSL client.
  125. """
  126. def __init__(self, host, port, bindAddress, ctxFactory, connector, reactor=None):
  127. # tcp.Client.__init__ depends on self.ctxFactory being set
  128. self.ctxFactory = ctxFactory
  129. tcp.Client.__init__(self, host, port, bindAddress, connector, reactor)
  130. def _connectDone(self):
  131. self.startTLS(self.ctxFactory)
  132. self.startWriting()
  133. tcp.Client._connectDone(self)
  134. @implementer(interfaces.ISSLTransport)
  135. class Server(tcp.Server):
  136. """
  137. I am an SSL server.
  138. """
  139. def __init__(self, *args, **kwargs):
  140. tcp.Server.__init__(self, *args, **kwargs)
  141. self.startTLS(self.server.ctxFactory)
  142. def getPeerCertificate(self):
  143. # ISSLTransport.getPeerCertificate
  144. raise NotImplementedError("Server.getPeerCertificate")
  145. class Port(tcp.Port):
  146. """
  147. I am an SSL port.
  148. """
  149. transport = Server
  150. _type = "TLS"
  151. def __init__(
  152. self, port, factory, ctxFactory, backlog=50, interface="", reactor=None
  153. ):
  154. tcp.Port.__init__(self, port, factory, backlog, interface, reactor)
  155. self.ctxFactory = ctxFactory
  156. def _getLogPrefix(self, factory):
  157. """
  158. Override the normal prefix to include an annotation indicating this is a
  159. port for TLS connections.
  160. """
  161. return tcp.Port._getLogPrefix(self, factory) + " (TLS)"
  162. class Connector(tcp.Connector):
  163. def __init__(
  164. self, host, port, factory, contextFactory, timeout, bindAddress, reactor=None
  165. ):
  166. self.contextFactory = contextFactory
  167. tcp.Connector.__init__(self, host, port, factory, timeout, bindAddress, reactor)
  168. # Force some parameter checking in pyOpenSSL. It's better to fail now
  169. # than after we've set up the transport.
  170. contextFactory.getContext()
  171. def _makeTransport(self):
  172. return Client(
  173. self.host,
  174. self.port,
  175. self.bindAddress,
  176. self.contextFactory,
  177. self,
  178. self.reactor,
  179. )
  180. from twisted.internet._sslverify import (
  181. DN,
  182. Certificate,
  183. CertificateRequest,
  184. DistinguishedName,
  185. KeyPair,
  186. OpenSSLAcceptableCiphers as AcceptableCiphers,
  187. OpenSSLCertificateOptions as CertificateOptions,
  188. OpenSSLDefaultPaths,
  189. OpenSSLDiffieHellmanParameters as DiffieHellmanParameters,
  190. PrivateCertificate,
  191. ProtocolNegotiationSupport,
  192. TLSVersion,
  193. VerificationError,
  194. optionsForClientTLS,
  195. platformTrust,
  196. protocolNegotiationMechanisms,
  197. trustRootFromCertificates,
  198. )
  199. __all__ = [
  200. "ContextFactory",
  201. "DefaultOpenSSLContextFactory",
  202. "ClientContextFactory",
  203. "DistinguishedName",
  204. "DN",
  205. "Certificate",
  206. "CertificateRequest",
  207. "PrivateCertificate",
  208. "KeyPair",
  209. "AcceptableCiphers",
  210. "CertificateOptions",
  211. "DiffieHellmanParameters",
  212. "platformTrust",
  213. "OpenSSLDefaultPaths",
  214. "TLSVersion",
  215. "VerificationError",
  216. "optionsForClientTLS",
  217. "ProtocolNegotiationSupport",
  218. "protocolNegotiationMechanisms",
  219. "trustRootFromCertificates",
  220. ]