1 """Class for post-handshake certificate checking."""
3 from utils.cryptomath import hashAndBase64
5 from X509CertChain import X509CertChain
10 """This class is passed to a handshake function to check the other
11 party's certificate chain.
13 If a handshake function completes successfully, but the Checker
14 judges the other party's certificate chain to be missing or
15 inadequate, a subclass of
16 L{tlslite.errors.TLSAuthenticationError} will be raised.
18 Currently, the Checker can check either an X.509 or a cryptoID
19 chain (for the latter, cryptoIDlib must be installed).
22 def __init__(self, cryptoID=None, protocol=None,
24 x509TrustList=None, x509CommonName=None,
25 checkResumedSession=False):
26 """Create a new Checker instance.
28 You must pass in one of these argument combinations:
29 - cryptoID[, protocol] (requires cryptoIDlib)
31 - x509TrustList[, x509CommonName] (requires cryptlib_py)
34 @param cryptoID: A cryptoID which the other party's certificate
35 chain must match. The cryptoIDlib module must be installed.
36 Mutually exclusive with all of the 'x509...' arguments.
39 @param protocol: A cryptoID protocol URI which the other
40 party's certificate chain must match. Requires the 'cryptoID'
43 @type x509Fingerprint: str
44 @param x509Fingerprint: A hex-encoded X.509 end-entity
45 fingerprint which the other party's end-entity certificate must
46 match. Mutually exclusive with the 'cryptoID' and
47 'x509TrustList' arguments.
49 @type x509TrustList: list of L{tlslite.X509.X509}
50 @param x509TrustList: A list of trusted root certificates. The
51 other party must present a certificate chain which extends to
52 one of these root certificates. The cryptlib_py module must be
53 installed. Mutually exclusive with the 'cryptoID' and
54 'x509Fingerprint' arguments.
56 @type x509CommonName: str
57 @param x509CommonName: The end-entity certificate's 'CN' field
58 must match this value. For a web server, this is typically a
59 server name such as 'www.amazon.com'. Mutually exclusive with
60 the 'cryptoID' and 'x509Fingerprint' arguments. Requires the
61 'x509TrustList' argument.
63 @type checkResumedSession: bool
64 @param checkResumedSession: If resumed sessions should be
65 checked. This defaults to False, on the theory that if the
66 session was checked once, we don't need to bother
70 if cryptoID and (x509Fingerprint or x509TrustList):
72 if x509Fingerprint and x509TrustList:
74 if x509CommonName and not x509TrustList:
76 if protocol and not cryptoID:
79 import cryptoIDlib #So we raise an error here
81 import cryptlib_py #So we raise an error here
82 self.cryptoID = cryptoID
83 self.protocol = protocol
84 self.x509Fingerprint = x509Fingerprint
85 self.x509TrustList = x509TrustList
86 self.x509CommonName = x509CommonName
87 self.checkResumedSession = checkResumedSession
89 def __call__(self, connection):
90 """Check a TLSConnection.
92 When a Checker is passed to a handshake function, this will
93 be called at the end of the function.
95 @type connection: L{tlslite.TLSConnection.TLSConnection}
96 @param connection: The TLSConnection to examine.
98 @raise tlslite.errors.TLSAuthenticationError: If the other
99 party's certificate chain is missing or bad.
101 if not self.checkResumedSession and connection.resumed:
104 if self.cryptoID or self.x509Fingerprint or self.x509TrustList:
105 if connection._client:
106 chain = connection.session.serverCertChain
108 chain = connection.session.clientCertChain
110 if self.x509Fingerprint or self.x509TrustList:
111 if isinstance(chain, X509CertChain):
112 if self.x509Fingerprint:
113 if chain.getFingerprint() != self.x509Fingerprint:
114 raise TLSFingerprintError(\
115 "X.509 fingerprint mismatch: %s, %s" % \
116 (chain.getFingerprint(), self.x509Fingerprint))
117 else: #self.x509TrustList
118 if not chain.validate(self.x509TrustList):
119 raise TLSValidationError("X.509 validation failure")
120 if self.x509CommonName and \
121 (chain.getCommonName() != self.x509CommonName):
122 raise TLSAuthorizationError(\
123 "X.509 Common Name mismatch: %s, %s" % \
124 (chain.getCommonName(), self.x509CommonName))
126 raise TLSAuthenticationTypeError()
128 raise TLSNoAuthenticationError()
130 import cryptoIDlib.CertChain
131 if isinstance(chain, cryptoIDlib.CertChain.CertChain):
132 if chain.cryptoID != self.cryptoID:
133 raise TLSFingerprintError(\
134 "cryptoID mismatch: %s, %s" % \
135 (chain.cryptoID, self.cryptoID))
137 if not chain.checkProtocol(self.protocol):
138 raise TLSAuthorizationError(\
139 "cryptoID protocol mismatch")
140 if not chain.validate():
141 raise TLSValidationError("cryptoID validation failure")
143 raise TLSAuthenticationTypeError()
145 raise TLSNoAuthenticationError()