1
# -*- test-case-name: twisted.test.test_sslverify -*-
2
# Copyright 2005 Divmod, Inc. See LICENSE file for details
5
from OpenSSL import SSL, crypto
7
from twisted.python import reflect, util
8
from twisted.internet.defer import Deferred
9
from twisted.internet.error import VerifyError, CertificateError
11
# Private - shared between all OpenSSLCertificateOptions, counts up to provide
12
# a unique session id for each context
13
_sessionCounter = itertools.count().next
15
class _SSLApplicationData(object):
19
class OpenSSLVerifyError(VerifyError):
21
_errorCodes = {0: ('X509_V_OK',
23
'the operation was successful. >'),
25
2: ('X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT',
26
'unable to get issuer certificate',
27
"The issuer certificate could not be found. This "
28
"occurs if the issuer certificate of an untrusted "
29
"certificate cannot be found."),
31
3: ('X509_V_ERR_UNABLE_TO_GET_CRL',
32
'unable to get certificate CRL',
33
"The CRL of a certificate could not be found. "
36
4: ('X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE',
37
"unable to decrypt certificate's signature",
38
"The certificate signature could not be decrypted. "
39
"This means that the actual signature value could not "
40
"be determined rather than it not matching the "
41
"expected value, this is only meaningful for RSA "
44
5: ('X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE',
45
"unable to decrypt CRL's signature",
46
"The CRL signature could not be decrypted. This "
47
"means that the actual signature value could not be "
48
"determined rather than it not matching the expected "
51
6: ('X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY',
52
'unable to decode issuer',
53
"Public key the public key in the certificate "
54
"SubjectPublicKeyInfo could not be read."),
56
7: ('X509_V_ERR_CERT_SIGNATURE_FAILURE',
57
'certificate signature failure',
58
'The signature of the certificate is invalid.'),
60
8: ('X509_V_ERR_CRL_SIGNATURE_FAILURE',
61
'CRL signature failure',
62
'The signature of the certificate is invalid. Unused.'),
64
9: ('X509_V_ERR_CERT_NOT_YET_VALID',
65
'certificate is not yet valid',
66
"The certificate is not yet valid. The notBefore "
67
"date is after the current time."),
69
10: ('X509_V_ERR_CERT_HAS_EXPIRED',
70
'certificate has expired',
71
"The certificate has expired. The notAfter date "
72
"is before the current time."),
74
11: ('X509_V_ERR_CRL_NOT_YET_VALID',
75
'CRL is not yet valid',
76
'The CRL is not yet valid. Unused.'),
78
12: ('X509_V_ERR_CRL_HAS_EXPIRED',
80
'The CRL has expired. Unused.'),
82
13: ('X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD',
83
"format error in certificate's notBefore field",
84
"The certificate's notBefore field contains an "
87
14: ('X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD',
88
"format error in certificate's notAfter field.",
89
"The certificate's notAfter field contains an "
92
15: ('X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD',
93
"format error in CRL's lastUpdate field",
94
"The CRL lastUpdate field contains an invalid "
97
16: ('X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD',
98
"format error in CRL's nextUpdate field",
99
"The CRL nextUpdate field contains an invalid "
102
17: ('X509_V_ERR_OUT_OF_MEM',
104
'An error occurred trying to allocate memory. '
105
'This should never happen.'),
107
18: ('X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT',
108
'self signed certificate',
109
'The passed certificate is self signed and the same '
110
'certificate cannot be found in the list of trusted '
113
19: ('X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN',
114
'self signed certificate in certificate chain',
115
'The certificate chain could be built up using the '
116
'untrusted certificates but the root could not be '
119
20: ('X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY',
120
'unable to get local issuer certificate',
121
'The issuer certificate of a locally looked up '
122
'certificate could not be found. This normally '
123
'means the list of trusted certificates is not '
126
21: ('X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE',
127
'unable to verify the first certificate',
128
'No signatures could be verified because the chain '
129
'contains only one certificate and it is not self '
132
22: ('X509_V_ERR_CERT_CHAIN_TOO_LONG',
133
'certificate chain too long',
134
'The certificate chain length is greater than the '
135
'supplied maximum depth. Unused.'),
137
23: ('X509_V_ERR_CERT_REVOKED',
138
'certificate revoked',
139
'The certificate has been revoked. Unused.'),
141
24: ('X509_V_ERR_INVALID_CA',
142
'invalid CA certificate',
143
'A CA certificate is invalid. Either it is not a CA '
144
'or its extensions are not consistent with the '
145
'supplied purpose.'),
147
25: ('X509_V_ERR_PATH_LENGTH_EXCEEDED',
148
'path length constraint exceeded',
149
'The basicConstraints pathlength parameter has been '
152
26: ('X509_V_ERR_INVALID_PURPOSE',
153
'unsupported certificate purpose',
154
'The supplied certificate cannot be used for the '
155
'specified purpose.'),
157
27: ('X509_V_ERR_CERT_UNTRUSTED',
158
'certificate not trusted',
159
'The root CA is not marked as trusted for the '
160
'specified purpose.'),
162
28: ('X509_V_ERR_CERT_REJECTED',
163
'certificate rejected',
164
'The root CA is marked to reject the specified '
167
29: ('X509_V_ERR_SUBJECT_ISSUER_MISMATCH',
168
'subject issuer mismatch',
169
'The current candidate issuer certificate was '
170
'rejected because its subject name did not match '
171
'the issuer name of the current certificate. Only '
172
'displayed when the issuer_checks option is set.'),
174
30: ('X509_V_ERR_AKID_SKID_MISMATCH',
175
'authority and subject key identifier mismatch',
176
'The current candidate issuer certificate was '
177
'rejected because its subject key identifier was '
178
'present and did not match the authority key '
179
'identifier current certificate. Only displayed '
180
'when the issuer_checks option is set.'),
182
31: ('X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH',
183
'authority and issuer serial number mismatch',
184
'The current candidate issuer certificate was '
185
'rejected because its issuer name and serial '
186
'number was present and did not match the '
187
'authority key identifier of the current '
188
'certificate. Only displayed when the issuer_checks '
191
32: ('X509_V_ERR_KEYUSAGE_NO_CERTSIGN',
192
'key usage does not include certificate',
193
'Signing the current candidate issuer certificate was '
194
'rejected because its keyUsage extension does not '
195
'permit certificate signing.'),
197
50: ('X509_V_ERR_APPLICATION_VERIFICATION',
198
'application verification failure',
199
'an application specific error. Unused.')}
202
def __init__(self, cert, errno, depth):
203
VerifyError.__init__(self, cert, errno, depth)
209
x = self._errorCodes.get(self.errno)
211
name, short, long = x
212
return 'Peer Certificate Verification Failed: %s (error code: %d)' % (
215
return "Peer Certificate Verification Failed for Unknown Reason"
222
'commonName': 'commonName',
224
'O': 'organizationName',
225
'organizationName': 'organizationName',
227
'OU': 'organizationalUnitName',
228
'organizationalUnitName': 'organizationalUnitName',
231
'localityName': 'localityName',
233
'ST': 'stateOrProvinceName',
234
'stateOrProvinceName': 'stateOrProvinceName',
237
'countryName': 'countryName',
239
'emailAddress': 'emailAddress'}
242
class DistinguishedName(dict):
244
Identify and describe an entity.
246
Distinguished names are used to provide a minimal amount of identifying
247
information about a certificate issuer or subject. They are commonly
248
created with one or more of the following fields::
252
organizationalUnitName (OU)
254
stateOrProvinceName (ST)
260
def __init__(self, **kw):
261
for k, v in kw.iteritems():
265
def _copyFrom(self, x509name):
267
for name in _x509names:
268
value = getattr(x509name, name, None)
269
if value is not None:
270
setattr(self, name, value)
273
def _copyInto(self, x509name):
274
for k, v in self.iteritems():
275
setattr(x509name, k, v)
279
return '<DN %s>' % (dict.__repr__(self)[1:-1])
282
def __getattr__(self, attr):
284
return self[_x509names[attr]]
286
raise AttributeError(attr)
289
def __setattr__(self, attr, value):
290
assert type(attr) is str
291
if not attr in _x509names:
292
raise AttributeError("%s is not a valid OpenSSL X509 name field" % (attr,))
293
realAttr = _x509names[attr]
294
value = value.encode('ascii')
295
assert type(value) is str
296
self[realAttr] = value
301
Return a multi-line, human-readable representation of this DN.
305
def uniqueValues(mapping):
306
return dict.fromkeys(mapping.itervalues()).keys()
307
for k in uniqueValues(_x509names):
308
label = util.nameToLabel(k)
309
lablen = max(len(label), lablen)
310
v = getattr(self, k, None)
314
for n, (label, attr) in enumerate(l):
315
l[n] = (label.rjust(lablen)+': '+ attr)
318
DN = DistinguishedName
322
def __init__(self, original):
323
self.original = original
325
def _copyName(self, suffix):
326
dn = DistinguishedName()
327
dn._copyFrom(getattr(self.original, 'get_'+suffix)())
330
def getSubject(self):
332
Retrieve the subject of this certificate.
334
@rtype: L{DistinguishedName}
335
@return: A copy of the subject of this certificate.
337
return self._copyName('subject')
341
def problemsFromTransport(tpt):
343
Retrieve the SSL errors associated with the given transport.
345
@type tpt: L{ISystemHandle} provider wrapper around an SSL connection.
346
@rtype: C{list} of L{OpenSSLVerifyError}.
348
return tpt.getHandle().get_context().get_app_data().problems
351
def _handleattrhelper(Class, transport, methodName):
353
(private) Helper for L{Certificate.peerFromTransport} and
354
L{Certificate.hostFromTransport} which checks for incompatible handle types
355
and null certificates and raises the appropriate exception or returns the
356
appropriate certificate object.
358
method = getattr(transport.getHandle(),
359
"get_%s_certificate" % (methodName,), None)
361
raise CertificateError(
362
"non-TLS transport %r did not have %s certificate" % (transport, methodName))
365
raise CertificateError(
366
"TLS transport %r did not have %s certificate" % (transport, methodName))
370
class Certificate(CertBase):
375
return '<%s Subject=%s Issuer=%s>' % (self.__class__.__name__,
376
self.getSubject().commonName,
377
self.getIssuer().commonName)
379
def __eq__(self, other):
380
if isinstance(other, Certificate):
381
return self.dump() == other.dump()
385
def __ne__(self, other):
386
return not self.__eq__(other)
389
def load(Class, requestData, format=crypto.FILETYPE_ASN1, args=()):
391
Load a certificate from an ASN.1- or PEM-format string.
395
return Class(crypto.load_certificate(format, requestData), *args)
396
load = classmethod(load)
402
Dump this certificate to a PEM-format data string.
406
return self.dump(crypto.FILETYPE_PEM)
409
def loadPEM(Class, data):
411
Load a certificate from a PEM-format data string.
415
return Class.load(data, crypto.FILETYPE_PEM)
416
loadPEM = classmethod(loadPEM)
419
def peerFromTransport(Class, transport):
421
Get the certificate for the remote end of the given transport.
423
@type: L{ISystemHandle}
426
@raise: L{CertificateError}, if the given transport does not have a peer
429
return _handleattrhelper(Class, transport, 'peer')
430
peerFromTransport = classmethod(peerFromTransport)
433
def hostFromTransport(Class, transport):
435
Get the certificate for the local end of the given transport.
437
@param transport: an L{ISystemHandle} provider; the transport we will
441
@raise: L{CertificateError}, if the given transport does not have a host
444
return _handleattrhelper(Class, transport, 'host')
445
hostFromTransport = classmethod(hostFromTransport)
448
def getPublicKey(self):
450
Get the public key for this certificate.
454
return PublicKey(self.original.get_pubkey())
457
def dump(self, format=crypto.FILETYPE_ASN1):
458
return crypto.dump_certificate(format, self.original)
461
def serialNumber(self):
463
Retrieve the serial number of this certificate.
467
return self.original.get_serial_number()
470
def digest(self, method='md5'):
472
Return a digest hash of this certificate using the specified hash
475
@param method: One of C{'md5'} or C{'sha'}.
478
return self.original.digest(method)
482
return '\n'.join(['Certificate For Subject:',
483
self.getSubject().inspect(),
485
self.getIssuer().inspect(),
486
'\nSerial Number: %d' % self.serialNumber(),
487
'Digest: %s' % self.digest()])
492
Return a multi-line, human-readable representation of this
493
Certificate, including information about the subject, issuer, and
496
return '\n'.join((self._inspect(), self.getPublicKey().inspect()))
501
Retrieve the issuer of this certificate.
503
@rtype: L{DistinguishedName}
504
@return: A copy of the issuer of this certificate.
506
return self._copyName('issuer')
509
def options(self, *authorities):
510
raise NotImplementedError('Possible, but doubtful we need this yet')
514
class CertificateRequest(CertBase):
516
An x509 certificate request.
518
Certificate requests are given to certificate authorities to be signed and
519
returned resulting in an actual certificate.
521
def load(Class, requestData, requestFormat=crypto.FILETYPE_ASN1):
522
req = crypto.load_certificate_request(requestFormat, requestData)
523
dn = DistinguishedName()
524
dn._copyFrom(req.get_subject())
525
if not req.verify(req.get_pubkey()):
526
raise VerifyError("Can't verify that request for %r is self-signed." % (dn,))
528
load = classmethod(load)
531
def dump(self, format=crypto.FILETYPE_ASN1):
532
return crypto.dump_certificate_request(format, self.original)
536
class PrivateCertificate(Certificate):
538
An x509 certificate and private key.
541
return Certificate.__repr__(self) + ' with ' + repr(self.privateKey)
544
def _setPrivateKey(self, privateKey):
545
if not privateKey.matches(self.getPublicKey()):
547
"Sanity check failed: Your certificate was not properly signed.")
548
self.privateKey = privateKey
552
def newCertificate(self, newCertData, format=crypto.FILETYPE_ASN1):
554
Create a new L{PrivateCertificate} from the given certificate data and
555
this instance's private key.
557
return self.load(newCertData, self.privateKey, format)
560
def load(Class, data, privateKey, format=crypto.FILETYPE_ASN1):
561
return Class._load(data, format)._setPrivateKey(privateKey)
562
load = classmethod(load)
566
return '\n'.join([Certificate._inspect(self),
567
self.privateKey.inspect()])
572
Dump both public and private parts of a private certificate to
575
return self.dump(crypto.FILETYPE_PEM) + self.privateKey.dump(crypto.FILETYPE_PEM)
578
def loadPEM(Class, data):
580
Load both private and public parts of a private certificate from a
581
chunk of PEM-format data.
583
return Class.load(data, KeyPair.load(data, crypto.FILETYPE_PEM),
585
loadPEM = classmethod(loadPEM)
588
def fromCertificateAndKeyPair(Class, certificateInstance, privateKey):
589
privcert = Class(certificateInstance.original)
590
return privcert._setPrivateKey(privateKey)
591
fromCertificateAndKeyPair = classmethod(fromCertificateAndKeyPair)
594
def options(self, *authorities):
595
options = dict(privateKey=self.privateKey.original,
596
certificate=self.original)
598
options.update(dict(verify=True,
599
requireCertificate=True,
600
caCerts=[auth.original for auth in authorities]))
601
return OpenSSLCertificateOptions(**options)
604
def certificateRequest(self, format=crypto.FILETYPE_ASN1,
605
digestAlgorithm='md5'):
606
return self.privateKey.certificateRequest(
612
def signCertificateRequest(self,
616
requestFormat=crypto.FILETYPE_ASN1,
617
certificateFormat=crypto.FILETYPE_ASN1):
618
issuer = self.getSubject()
619
return self.privateKey.signCertificateRequest(
628
def signRequestObject(self, certificateRequest, serialNumber,
629
secondsToExpiry=60 * 60 * 24 * 365, # One year
630
digestAlgorithm='md5'):
631
return self.privateKey.signRequestObject(self.getSubject(),
639
def __init__(self, osslpkey):
640
self.original = osslpkey
641
req1 = crypto.X509Req()
642
req1.set_pubkey(osslpkey)
643
self._emptyReq = crypto.dump_certificate_request(crypto.FILETYPE_ASN1, req1)
646
def matches(self, otherKey):
647
return self._emptyReq == otherKey._emptyReq
650
# XXX This could be a useful method, but sometimes it triggers a segfault,
651
# so we'll steer clear for now.
652
# def verifyCertificate(self, certificate):
654
# returns None, or raises a VerifyError exception if the certificate
655
# could not be verified.
657
# if not certificate.original.verify(self.original):
658
# raise VerifyError("We didn't sign that certificate.")
661
return '<%s %s>' % (self.__class__.__name__, self.keyHash())
666
MD5 hex digest of signature on an empty certificate request with this
669
return md5.md5(self._emptyReq).hexdigest()
673
return 'Public Key with Hash: %s' % (self.keyHash(),)
677
class KeyPair(PublicKey):
679
def load(Class, data, format=crypto.FILETYPE_ASN1):
680
return Class(crypto.load_privatekey(format, data))
681
load = classmethod(load)
684
def dump(self, format=crypto.FILETYPE_ASN1):
685
return crypto.dump_privatekey(format, self.original)
688
def __getstate__(self):
692
def __setstate__(self, state):
693
self.__init__(crypto.load_privatekey(crypto.FILETYPE_ASN1, state))
697
t = self.original.type()
698
if t == crypto.TYPE_RSA:
700
elif t == crypto.TYPE_DSA:
703
ts = '(Unknown Type!)'
704
L = (self.original.bits(), ts, self.keyHash())
705
return '%s-bit %s Key Pair with Hash: %s' % L
708
def generate(Class, kind=crypto.TYPE_RSA, size=1024):
710
pkey.generate_key(kind, size)
714
def newCertificate(self, newCertData, format=crypto.FILETYPE_ASN1):
715
return PrivateCertificate.load(newCertData, self, format)
716
generate = classmethod(generate)
719
def requestObject(self, distinguishedName, digestAlgorithm='md5'):
720
req = crypto.X509Req()
721
req.set_pubkey(self.original)
722
distinguishedName._copyInto(req.get_subject())
723
req.sign(self.original, digestAlgorithm)
724
return CertificateRequest(req)
727
def certificateRequest(self, distinguishedName,
728
format=crypto.FILETYPE_ASN1,
729
digestAlgorithm='md5'):
730
"""Create a certificate request signed with this key.
732
@return: a string, formatted according to the 'format' argument.
734
return self.requestObject(distinguishedName, digestAlgorithm).dump(format)
737
def signCertificateRequest(self,
738
issuerDistinguishedName,
742
requestFormat=crypto.FILETYPE_ASN1,
743
certificateFormat=crypto.FILETYPE_ASN1,
744
secondsToExpiry=60 * 60 * 24 * 365, # One year
745
digestAlgorithm='md5'):
747
Given a blob of certificate request data and a certificate authority's
748
DistinguishedName, return a blob of signed certificate data.
750
If verifyDNCallback returns a Deferred, I will return a Deferred which
751
fires the data when that Deferred has completed.
753
hlreq = CertificateRequest.load(requestData, requestFormat)
755
dn = hlreq.getSubject()
756
vval = verifyDNCallback(dn)
760
raise VerifyError("DN callback %r rejected request DN %r" % (verifyDNCallback, dn))
761
return self.signRequestObject(issuerDistinguishedName, hlreq,
762
serialNumber, secondsToExpiry, digestAlgorithm).dump(certificateFormat)
764
if isinstance(vval, Deferred):
765
return vval.addCallback(verified)
767
return verified(vval)
770
def signRequestObject(self,
771
issuerDistinguishedName,
774
secondsToExpiry=60 * 60 * 24 * 365, # One year
775
digestAlgorithm='md5'):
777
Sign a CertificateRequest instance, returning a Certificate instance.
779
req = requestObject.original
780
dn = requestObject.getSubject()
782
issuerDistinguishedName._copyInto(cert.get_issuer())
783
cert.set_subject(req.get_subject())
784
cert.set_pubkey(req.get_pubkey())
785
cert.gmtime_adj_notBefore(0)
786
cert.gmtime_adj_notAfter(secondsToExpiry)
787
cert.set_serial_number(serialNumber)
788
cert.sign(self.original, digestAlgorithm)
789
return Certificate(cert)
792
def selfSignedCert(self, serialNumber, **kw):
794
return PrivateCertificate.fromCertificateAndKeyPair(
795
self.signRequestObject(dn, self.requestObject(dn), serialNumber),
800
class OpenSSLCertificateOptions(object):
802
A factory for SSL context objects for both SSL servers and clients.
806
# Older versions of PyOpenSSL didn't provide OP_ALL. Fudge it here, just in case.
807
_OP_ALL = getattr(SSL, 'OP_ALL', 0x0000FFFF)
809
method = SSL.TLSv1_METHOD
818
requireCertificate=True,
820
enableSingleUseKeys=True,
822
fixBrokenPeers=False):
824
Create an OpenSSL context SSL connection context factory.
826
@param privateKey: A PKey object holding the private key.
828
@param certificate: An X509 object holding the certificate.
830
@param method: The SSL protocol to use, one of SSLv23_METHOD,
831
SSLv2_METHOD, SSLv3_METHOD, TLSv1_METHOD. Defaults to TLSv1_METHOD.
833
@param verify: If True, verify certificates received from the peer and
834
fail the handshake if verification fails. Otherwise, allow anonymous
835
sessions and sessions with certificates which fail validation. By
836
default this is False.
838
@param caCerts: List of certificate authority certificates to
839
send to the client when requesting a certificate. Only used if verify
840
is True, and if verify is True, either this must be specified or
841
caCertsFile must be given. Since verify is False by default,
842
this is None by default.
844
@param verifyDepth: Depth in certificate chain down to which to verify.
845
If unspecified, use the underlying default (9).
847
@param requireCertificate: If True, do not allow anonymous sessions.
849
@param verifyOnce: If True, do not re-verify the certificate
850
on session resumption.
852
@param enableSingleUseKeys: If True, generate a new key whenever
853
ephemeral DH parameters are used to prevent small subgroup attacks.
855
@param enableSessions: If True, set a session ID on each context. This
856
allows a shortened handshake to be used when a known client reconnects.
858
@param fixBrokenPeers: If True, enable various non-spec protocol fixes
859
for broken SSL implementations. This should be entirely safe,
860
according to the OpenSSL documentation, but YMMV. This option is now
861
off by default, because it causes problems with connections between
862
peers using OpenSSL 0.9.8a.
865
assert (privateKey is None) == (certificate is None), "Specify neither or both of privateKey and certificate"
866
self.privateKey = privateKey
867
self.certificate = certificate
868
if method is not None:
872
assert ((verify and caCerts) or
873
(not verify)), "Specify client CA certificate information if and only if enabling certificate verification"
875
self.caCerts = caCerts
876
self.verifyDepth = verifyDepth
877
self.requireCertificate = requireCertificate
878
self.verifyOnce = verifyOnce
879
self.enableSingleUseKeys = enableSingleUseKeys
880
self.enableSessions = enableSessions
881
self.fixBrokenPeers = fixBrokenPeers
884
def __getstate__(self):
885
d = self.__dict__.copy()
893
def __setstate__(self, state):
894
self.__dict__ = state
897
def getContext(self):
898
"""Return a SSL.Context object.
900
if self._context is None:
901
self._context = self._makeContext()
905
def _makeContext(self):
906
ctx = SSL.Context(self.method)
907
ctx.set_app_data(_SSLApplicationData())
909
if self.certificate is not None and self.privateKey is not None:
910
ctx.use_certificate(self.certificate)
911
ctx.use_privatekey(self.privateKey)
913
ctx.check_privatekey()
915
verifyFlags = SSL.VERIFY_NONE
917
verifyFlags = SSL.VERIFY_PEER
918
if self.requireCertificate:
919
verifyFlags |= SSL.VERIFY_FAIL_IF_NO_PEER_CERT
921
verifyFlags |= SSL.VERIFY_CLIENT_ONCE
923
store = ctx.get_cert_store()
924
for cert in self.caCerts:
927
def _trackVerificationProblems(conn,cert,errno,depth,preverify_ok):
928
# retcode is the answer OpenSSL's default verifier would have
929
# given, had we allowed it to run.
931
ctx.get_app_data().problems.append(OpenSSLVerifyError(cert, errno, depth))
933
ctx.set_verify(verifyFlags, _trackVerificationProblems)
935
if self.verifyDepth is not None:
936
ctx.set_verify_depth(self.verifyDepth)
938
if self.enableSingleUseKeys:
939
ctx.set_options(SSL.OP_SINGLE_DH_USE)
941
if self.fixBrokenPeers:
942
ctx.set_options(self._OP_ALL)
944
if self.enableSessions:
945
sessionName = md5.md5("%s-%d" % (reflect.qual(self.__class__), _sessionCounter())).hexdigest()
946
ctx.set_session_id(sessionName)