Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/twisted/internet/ssl.py: 59%
75 statements
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-07 06:38 +0000
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-07 06:38 +0000
1# -*- test-case-name: twisted.test.test_ssl -*-
2# Copyright (c) Twisted Matrix Laboratories.
3# See LICENSE for details.
5"""
6This module implements Transport Layer Security (TLS) support for Twisted. It
7requires U{PyOpenSSL <https://pypi.python.org/pypi/pyOpenSSL>}.
9If you wish to establish a TLS connection, please use one of the following
10APIs:
12 - SSL endpoints for L{servers
13 <twisted.internet.endpoints.SSL4ServerEndpoint>} and L{clients
14 <twisted.internet.endpoints.SSL4ClientEndpoint>}
16 - L{startTLS <twisted.internet.interfaces.ITLSTransport.startTLS>}
18 - L{connectSSL <twisted.internet.interfaces.IReactorSSL.connectSSL>}
20 - L{listenSSL <twisted.internet.interfaces.IReactorSSL.listenSSL>}
22These APIs all require a C{contextFactory} argument that specifies their
23security properties, such as certificate, private key, certificate authorities
24to verify the peer, allowed TLS protocol versions, cipher suites, and so on.
25The recommended value for this argument is a L{CertificateOptions} instance;
26see its documentation for an explanation of the available options.
28The C{contextFactory} name is a bit of an anachronism now, as context factories
29have been replaced with "connection creators", but these objects serve the same
30role.
32Be warned that implementing your own connection creator (i.e.: value for the
33C{contextFactory}) is both difficult and dangerous; the Twisted team has worked
34hard to make L{CertificateOptions}' API comprehensible and unsurprising, and
35the Twisted team is actively maintaining it to ensure that it becomes more
36secure over time.
38If you are really absolutely sure that you want to take on the risk of
39implementing your own connection creator based on the pyOpenSSL API, see the
40L{server connection creator
41<twisted.internet.interfaces.IOpenSSLServerConnectionCreator>} and L{client
42connection creator
43<twisted.internet.interfaces.IOpenSSLServerConnectionCreator>} interfaces.
45Developers using Twisted, please ignore the L{Port}, L{Connector}, and
46L{Client} classes defined here, as these are details of certain reactors' TLS
47implementations, exposed by accident (and remaining here only for compatibility
48reasons). If you wish to establish a TLS connection, please use one of the
49APIs listed above.
51@note: "SSL" (Secure Sockets Layer) is an antiquated synonym for "TLS"
52 (Transport Layer Security). You may see these terms used interchangeably
53 throughout the documentation.
54"""
57from zope.interface import implementedBy, implementer, implementer_only
59# System imports
60from OpenSSL import SSL
62# Twisted imports
63from twisted.internet import interfaces, tcp
65supported = True
68@implementer(interfaces.IOpenSSLContextFactory)
69class ContextFactory:
70 """A factory for SSL context objects, for server SSL connections."""
72 isClient = 0
74 def getContext(self):
75 """Return a SSL.Context object. override in subclasses."""
76 raise NotImplementedError
79class DefaultOpenSSLContextFactory(ContextFactory):
80 """
81 L{DefaultOpenSSLContextFactory} is a factory for server-side SSL context
82 objects. These objects define certain parameters related to SSL
83 handshakes and the subsequent connection.
85 @ivar _contextFactory: A callable which will be used to create new
86 context objects. This is typically L{OpenSSL.SSL.Context}.
87 """
89 _context = None
91 def __init__(
92 self,
93 privateKeyFileName,
94 certificateFileName,
95 sslmethod=SSL.TLS_METHOD,
96 _contextFactory=SSL.Context,
97 ):
98 """
99 @param privateKeyFileName: Name of a file containing a private key
100 @param certificateFileName: Name of a file containing a certificate
101 @param sslmethod: The SSL method to use
102 """
103 self.privateKeyFileName = privateKeyFileName
104 self.certificateFileName = certificateFileName
105 self.sslmethod = sslmethod
106 self._contextFactory = _contextFactory
108 # Create a context object right now. This is to force validation of
109 # the given parameters so that errors are detected earlier rather
110 # than later.
111 self.cacheContext()
113 def cacheContext(self):
114 if self._context is None:
115 ctx = self._contextFactory(self.sslmethod)
116 # Disallow SSLv2! It's insecure! SSLv3 has been around since
117 # 1996. It's time to move on.
118 ctx.set_options(SSL.OP_NO_SSLv2)
119 ctx.use_certificate_file(self.certificateFileName)
120 ctx.use_privatekey_file(self.privateKeyFileName)
121 self._context = ctx
123 def __getstate__(self):
124 d = self.__dict__.copy()
125 del d["_context"]
126 return d
128 def __setstate__(self, state):
129 self.__dict__ = state
131 def getContext(self):
132 """
133 Return an SSL context.
134 """
135 return self._context
138@implementer(interfaces.IOpenSSLContextFactory)
139class ClientContextFactory:
140 """A context factory for SSL clients."""
142 isClient = 1
144 # TLS_METHOD allows negotiation of multiple TLS versions.
145 method = SSL.TLS_METHOD
147 _contextFactory = SSL.Context
149 def getContext(self):
150 ctx = self._contextFactory(self.method)
151 ctx.set_options(
152 SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3 | SSL.OP_NO_TLSv1 | SSL.OP_NO_TLSv1_1
153 )
154 return ctx
157@implementer_only(
158 interfaces.ISSLTransport,
159 *(i for i in implementedBy(tcp.Client) if i != interfaces.ITLSTransport),
160)
161class Client(tcp.Client):
162 """
163 I am an SSL client.
164 """
166 def __init__(self, host, port, bindAddress, ctxFactory, connector, reactor=None):
167 # tcp.Client.__init__ depends on self.ctxFactory being set
168 self.ctxFactory = ctxFactory
169 tcp.Client.__init__(self, host, port, bindAddress, connector, reactor)
171 def _connectDone(self):
172 self.startTLS(self.ctxFactory)
173 self.startWriting()
174 tcp.Client._connectDone(self)
177@implementer(interfaces.ISSLTransport)
178class Server(tcp.Server):
179 """
180 I am an SSL server.
181 """
183 def __init__(self, *args, **kwargs):
184 tcp.Server.__init__(self, *args, **kwargs)
185 self.startTLS(self.server.ctxFactory)
187 def getPeerCertificate(self):
188 # ISSLTransport.getPeerCertificate
189 raise NotImplementedError("Server.getPeerCertificate")
192class Port(tcp.Port):
193 """
194 I am an SSL port.
195 """
197 transport = Server
199 _type = "TLS"
201 def __init__(
202 self, port, factory, ctxFactory, backlog=50, interface="", reactor=None
203 ):
204 tcp.Port.__init__(self, port, factory, backlog, interface, reactor)
205 self.ctxFactory = ctxFactory
207 def _getLogPrefix(self, factory):
208 """
209 Override the normal prefix to include an annotation indicating this is a
210 port for TLS connections.
211 """
212 return tcp.Port._getLogPrefix(self, factory) + " (TLS)"
215class Connector(tcp.Connector):
216 def __init__(
217 self, host, port, factory, contextFactory, timeout, bindAddress, reactor=None
218 ):
219 self.contextFactory = contextFactory
220 tcp.Connector.__init__(self, host, port, factory, timeout, bindAddress, reactor)
222 # Force some parameter checking in pyOpenSSL. It's better to fail now
223 # than after we've set up the transport.
224 contextFactory.getContext()
226 def _makeTransport(self):
227 return Client(
228 self.host,
229 self.port,
230 self.bindAddress,
231 self.contextFactory,
232 self,
233 self.reactor,
234 )
237from twisted.internet._sslverify import (
238 DN,
239 Certificate,
240 CertificateRequest,
241 DistinguishedName,
242 KeyPair,
243 OpenSSLAcceptableCiphers as AcceptableCiphers,
244 OpenSSLCertificateOptions as CertificateOptions,
245 OpenSSLDefaultPaths,
246 OpenSSLDiffieHellmanParameters as DiffieHellmanParameters,
247 PrivateCertificate,
248 ProtocolNegotiationSupport,
249 TLSVersion,
250 VerificationError,
251 optionsForClientTLS,
252 platformTrust,
253 protocolNegotiationMechanisms,
254 trustRootFromCertificates,
255)
257__all__ = [
258 "ContextFactory",
259 "DefaultOpenSSLContextFactory",
260 "ClientContextFactory",
261 "DistinguishedName",
262 "DN",
263 "Certificate",
264 "CertificateRequest",
265 "PrivateCertificate",
266 "KeyPair",
267 "AcceptableCiphers",
268 "CertificateOptions",
269 "DiffieHellmanParameters",
270 "platformTrust",
271 "OpenSSLDefaultPaths",
272 "TLSVersion",
273 "VerificationError",
274 "optionsForClientTLS",
275 "ProtocolNegotiationSupport",
276 "protocolNegotiationMechanisms",
277 "trustRootFromCertificates",
278]