RCS file: /cvs/Twisted/twisted/internet/ssl.py,v
retrieving revision 1.44
diff -u -r1.44 ssl.py
|
|
|
45 | 45 | |
46 | 46 | # System imports |
47 | 47 | from OpenSSL import SSL |
| 48 | import md5 |
48 | 49 | import socket |
49 | 50 | |
| 51 | # Hack! This should be in the python SSL interface, *but isn't*. |
| 52 | # (grumblegrumble) |
| 53 | SSL_OP_ALL = 0x0000FFFF |
| 54 | |
50 | 55 | # sibling imports |
51 | 56 | import tcp, main, interfaces |
52 | 57 | |
… |
… |
|
63 | 68 | """Return a SSL.Context object. override in subclasses.""" |
64 | 69 | raise NotImplementedError |
65 | 70 | |
| 71 | NO_VERIFY_CERT, VERIFY_CERT, REQUIRE_CERT = range(3) |
66 | 72 | |
67 | 73 | class DefaultOpenSSLContextFactory(ContextFactory): |
68 | | |
| 74 | _sessionIdCtxNum = 0 |
69 | 75 | def __init__(self, privateKeyFileName, certificateFileName, |
70 | | sslmethod=SSL.SSLv23_METHOD): |
| 76 | sslmethod=SSL.SSLv23_METHOD, |
| 77 | verifyPeer=NO_VERIFY_CERT, verifyDepth=10, |
| 78 | clientCACertsFile=None): |
| 79 | """Initialize an SSL server context. |
| 80 | |
| 81 | privateKeyFileName and certificateFileName should be set to the |
| 82 | PEM-encoded key and certificates for this server. |
| 83 | |
| 84 | verifyPeer can be set to NO_VERIFY_CERT (no verification), |
| 85 | VERIFY_CERT (verify client cert but don't fail if none is given), |
| 86 | or REQUIRE_CERT (verify and require client cert). |
| 87 | |
| 88 | verifyDepth sets how long a certificate chain is allowed. |
| 89 | |
| 90 | clientCACertsFile can be set to a file containing (PEM-format) |
| 91 | certificates of the CAs to verify clients again. This must be |
| 92 | set if verifyPeer is non-zero. |
| 93 | |
| 94 | """ |
71 | 95 | self.privateKeyFileName = privateKeyFileName |
72 | 96 | self.certificateFileName = certificateFileName |
73 | 97 | self.sslmethod = sslmethod |
| 98 | self.verifyPeer = verifyPeer |
| 99 | self.verifyDepth = verifyDepth |
| 100 | self.clientCACertsFile = clientCACertsFile |
74 | 101 | self.cacheContext() |
75 | 102 | |
76 | 103 | def cacheContext(self): |
77 | 104 | ctx = SSL.Context(self.sslmethod) |
78 | 105 | ctx.use_certificate_file(self.certificateFileName) |
79 | 106 | ctx.use_privatekey_file(self.privateKeyFileName) |
| 107 | |
| 108 | ctx.set_verify_depth(self.verifyDepth) |
| 109 | |
| 110 | if self.clientCACertsFile: |
| 111 | ctx.load_client_ca(self.clientCACertsFile) |
| 112 | ctx.load_verify_locations(self.clientCACertsFile) |
| 113 | |
| 114 | if self.verifyPeer != NO_VERIFY_CERT: |
| 115 | callback = lambda conn,cert,errno,depth,retcode: retcode |
| 116 | if self.verifyPeer == REQUIRE_CERT: |
| 117 | options = SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT |
| 118 | else: |
| 119 | options = SSL.VERIFY_PEER |
| 120 | ctx.set_verify(options, callback) |
| 121 | |
| 122 | # turn on fixing SSL client bugs |
| 123 | ctx.set_options(SSL_OP_ALL|SSL.OP_SINGLE_DH_USE) |
| 124 | |
| 125 | # session id is supposed to be unique between servers in this process. |
| 126 | # i'm unsure what the point is, but it's required. In the sample |
| 127 | # code (1 server), it's simply set to 1. |
| 128 | DefaultOpenSSLContextFactory._sessionIdCtxNum = DefaultOpenSSLContextFactory._sessionIdCtxNum + 1 |
| 129 | ctx.set_session_id(md5.new("DefaultOpenSSLContextFactory%d"%DefaultOpenSSLContextFactory._sessionIdCtxNum).digest()) |
80 | 130 | self._context = ctx |
81 | 131 | |
82 | 132 | def __getstate__(self): |
… |
… |
|
184 | 234 | def getDestination(self): |
185 | 235 | return ('SSL', self.host, self.port) |
186 | 236 | |
187 | | __all__ = ["ContextFactory", "DefaultOpenSSLContextFactory", "ClientContextFactory"] |
| 237 | __all__ = ["ContextFactory", "DefaultOpenSSLContextFactory", "ClientContextFactory", "NO_VERIFY_CERT", "VERIFY_CERT", "REQUIRE_CERT"] |
188 | 238 | |
189 | 239 | supported = True |