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

1# -*- test-case-name: twisted.test.test_ssl -*- 

2# Copyright (c) Twisted Matrix Laboratories. 

3# See LICENSE for details. 

4 

5""" 

6This module implements Transport Layer Security (TLS) support for Twisted. It 

7requires U{PyOpenSSL <https://pypi.python.org/pypi/pyOpenSSL>}. 

8 

9If you wish to establish a TLS connection, please use one of the following 

10APIs: 

11 

12 - SSL endpoints for L{servers 

13 <twisted.internet.endpoints.SSL4ServerEndpoint>} and L{clients 

14 <twisted.internet.endpoints.SSL4ClientEndpoint>} 

15 

16 - L{startTLS <twisted.internet.interfaces.ITLSTransport.startTLS>} 

17 

18 - L{connectSSL <twisted.internet.interfaces.IReactorSSL.connectSSL>} 

19 

20 - L{listenSSL <twisted.internet.interfaces.IReactorSSL.listenSSL>} 

21 

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. 

27 

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. 

31 

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. 

37 

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. 

44 

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. 

50 

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""" 

55 

56 

57from zope.interface import implementedBy, implementer, implementer_only 

58 

59# System imports 

60from OpenSSL import SSL 

61 

62# Twisted imports 

63from twisted.internet import interfaces, tcp 

64 

65supported = True 

66 

67 

68@implementer(interfaces.IOpenSSLContextFactory) 

69class ContextFactory: 

70 """A factory for SSL context objects, for server SSL connections.""" 

71 

72 isClient = 0 

73 

74 def getContext(self): 

75 """Return a SSL.Context object. override in subclasses.""" 

76 raise NotImplementedError 

77 

78 

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. 

84 

85 @ivar _contextFactory: A callable which will be used to create new 

86 context objects. This is typically L{OpenSSL.SSL.Context}. 

87 """ 

88 

89 _context = None 

90 

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 

107 

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() 

112 

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 

122 

123 def __getstate__(self): 

124 d = self.__dict__.copy() 

125 del d["_context"] 

126 return d 

127 

128 def __setstate__(self, state): 

129 self.__dict__ = state 

130 

131 def getContext(self): 

132 """ 

133 Return an SSL context. 

134 """ 

135 return self._context 

136 

137 

138@implementer(interfaces.IOpenSSLContextFactory) 

139class ClientContextFactory: 

140 """A context factory for SSL clients.""" 

141 

142 isClient = 1 

143 

144 # TLS_METHOD allows negotiation of multiple TLS versions. 

145 method = SSL.TLS_METHOD 

146 

147 _contextFactory = SSL.Context 

148 

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 

155 

156 

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 """ 

165 

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) 

170 

171 def _connectDone(self): 

172 self.startTLS(self.ctxFactory) 

173 self.startWriting() 

174 tcp.Client._connectDone(self) 

175 

176 

177@implementer(interfaces.ISSLTransport) 

178class Server(tcp.Server): 

179 """ 

180 I am an SSL server. 

181 """ 

182 

183 def __init__(self, *args, **kwargs): 

184 tcp.Server.__init__(self, *args, **kwargs) 

185 self.startTLS(self.server.ctxFactory) 

186 

187 def getPeerCertificate(self): 

188 # ISSLTransport.getPeerCertificate 

189 raise NotImplementedError("Server.getPeerCertificate") 

190 

191 

192class Port(tcp.Port): 

193 """ 

194 I am an SSL port. 

195 """ 

196 

197 transport = Server 

198 

199 _type = "TLS" 

200 

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 

206 

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)" 

213 

214 

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) 

221 

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() 

225 

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 ) 

235 

236 

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) 

256 

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]