| Index: third_party/twisted_8_1/twisted/internet/_sslverify.py
|
| diff --git a/third_party/twisted_8_1/twisted/internet/_sslverify.py b/third_party/twisted_8_1/twisted/internet/_sslverify.py
|
| deleted file mode 100644
|
| index cde31f74df3649981a912ba04fd55084634ec390..0000000000000000000000000000000000000000
|
| --- a/third_party/twisted_8_1/twisted/internet/_sslverify.py
|
| +++ /dev/null
|
| @@ -1,949 +0,0 @@
|
| -# -*- test-case-name: twisted.test.test_sslverify -*-
|
| -# Copyright 2005 Divmod, Inc. See LICENSE file for details
|
| -
|
| -import hashlib
|
| -import itertools
|
| -from OpenSSL import SSL, crypto
|
| -
|
| -from twisted.python import reflect, util
|
| -from twisted.internet.defer import Deferred
|
| -from twisted.internet.error import VerifyError, CertificateError
|
| -
|
| -# Private - shared between all OpenSSLCertificateOptions, counts up to provide
|
| -# a unique session id for each context
|
| -_sessionCounter = itertools.count().next
|
| -
|
| -class _SSLApplicationData(object):
|
| - def __init__(self):
|
| - self.problems = []
|
| -
|
| -class OpenSSLVerifyError(VerifyError):
|
| -
|
| - _errorCodes = {0: ('X509_V_OK',
|
| - 'ok',
|
| - 'the operation was successful. >'),
|
| -
|
| - 2: ('X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT',
|
| - 'unable to get issuer certificate',
|
| - "The issuer certificate could not be found. This "
|
| - "occurs if the issuer certificate of an untrusted "
|
| - "certificate cannot be found."),
|
| -
|
| - 3: ('X509_V_ERR_UNABLE_TO_GET_CRL',
|
| - 'unable to get certificate CRL',
|
| - "The CRL of a certificate could not be found. "
|
| - "Unused."),
|
| -
|
| - 4: ('X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE',
|
| - "unable to decrypt certificate's signature",
|
| - "The certificate signature could not be decrypted. "
|
| - "This means that the actual signature value could not "
|
| - "be determined rather than it not matching the "
|
| - "expected value, this is only meaningful for RSA "
|
| - "keys."),
|
| -
|
| - 5: ('X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE',
|
| - "unable to decrypt CRL's signature",
|
| - "The CRL signature could not be decrypted. This "
|
| - "means that the actual signature value could not be "
|
| - "determined rather than it not matching the expected "
|
| - "value. Unused."),
|
| -
|
| - 6: ('X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY',
|
| - 'unable to decode issuer',
|
| - "Public key the public key in the certificate "
|
| - "SubjectPublicKeyInfo could not be read."),
|
| -
|
| - 7: ('X509_V_ERR_CERT_SIGNATURE_FAILURE',
|
| - 'certificate signature failure',
|
| - 'The signature of the certificate is invalid.'),
|
| -
|
| - 8: ('X509_V_ERR_CRL_SIGNATURE_FAILURE',
|
| - 'CRL signature failure',
|
| - 'The signature of the certificate is invalid. Unused.'),
|
| -
|
| - 9: ('X509_V_ERR_CERT_NOT_YET_VALID',
|
| - 'certificate is not yet valid',
|
| - "The certificate is not yet valid. The notBefore "
|
| - "date is after the current time."),
|
| -
|
| - 10: ('X509_V_ERR_CERT_HAS_EXPIRED',
|
| - 'certificate has expired',
|
| - "The certificate has expired. The notAfter date "
|
| - "is before the current time."),
|
| -
|
| - 11: ('X509_V_ERR_CRL_NOT_YET_VALID',
|
| - 'CRL is not yet valid',
|
| - 'The CRL is not yet valid. Unused.'),
|
| -
|
| - 12: ('X509_V_ERR_CRL_HAS_EXPIRED',
|
| - 'CRL has expired',
|
| - 'The CRL has expired. Unused.'),
|
| -
|
| - 13: ('X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD',
|
| - "format error in certificate's notBefore field",
|
| - "The certificate's notBefore field contains an "
|
| - "invalid time."),
|
| -
|
| - 14: ('X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD',
|
| - "format error in certificate's notAfter field.",
|
| - "The certificate's notAfter field contains an "
|
| - "invalid time."),
|
| -
|
| - 15: ('X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD',
|
| - "format error in CRL's lastUpdate field",
|
| - "The CRL lastUpdate field contains an invalid "
|
| - "time. Unused."),
|
| -
|
| - 16: ('X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD',
|
| - "format error in CRL's nextUpdate field",
|
| - "The CRL nextUpdate field contains an invalid "
|
| - "time. Unused."),
|
| -
|
| - 17: ('X509_V_ERR_OUT_OF_MEM',
|
| - 'out of memory',
|
| - 'An error occurred trying to allocate memory. '
|
| - 'This should never happen.'),
|
| -
|
| - 18: ('X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT',
|
| - 'self signed certificate',
|
| - 'The passed certificate is self signed and the same '
|
| - 'certificate cannot be found in the list of trusted '
|
| - 'certificates.'),
|
| -
|
| - 19: ('X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN',
|
| - 'self signed certificate in certificate chain',
|
| - 'The certificate chain could be built up using the '
|
| - 'untrusted certificates but the root could not be '
|
| - 'found locally.'),
|
| -
|
| - 20: ('X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY',
|
| - 'unable to get local issuer certificate',
|
| - 'The issuer certificate of a locally looked up '
|
| - 'certificate could not be found. This normally '
|
| - 'means the list of trusted certificates is not '
|
| - 'complete.'),
|
| -
|
| - 21: ('X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE',
|
| - 'unable to verify the first certificate',
|
| - 'No signatures could be verified because the chain '
|
| - 'contains only one certificate and it is not self '
|
| - 'signed.'),
|
| -
|
| - 22: ('X509_V_ERR_CERT_CHAIN_TOO_LONG',
|
| - 'certificate chain too long',
|
| - 'The certificate chain length is greater than the '
|
| - 'supplied maximum depth. Unused.'),
|
| -
|
| - 23: ('X509_V_ERR_CERT_REVOKED',
|
| - 'certificate revoked',
|
| - 'The certificate has been revoked. Unused.'),
|
| -
|
| - 24: ('X509_V_ERR_INVALID_CA',
|
| - 'invalid CA certificate',
|
| - 'A CA certificate is invalid. Either it is not a CA '
|
| - 'or its extensions are not consistent with the '
|
| - 'supplied purpose.'),
|
| -
|
| - 25: ('X509_V_ERR_PATH_LENGTH_EXCEEDED',
|
| - 'path length constraint exceeded',
|
| - 'The basicConstraints pathlength parameter has been '
|
| - 'exceeded.'),
|
| -
|
| - 26: ('X509_V_ERR_INVALID_PURPOSE',
|
| - 'unsupported certificate purpose',
|
| - 'The supplied certificate cannot be used for the '
|
| - 'specified purpose.'),
|
| -
|
| - 27: ('X509_V_ERR_CERT_UNTRUSTED',
|
| - 'certificate not trusted',
|
| - 'The root CA is not marked as trusted for the '
|
| - 'specified purpose.'),
|
| -
|
| - 28: ('X509_V_ERR_CERT_REJECTED',
|
| - 'certificate rejected',
|
| - 'The root CA is marked to reject the specified '
|
| - 'purpose.'),
|
| -
|
| - 29: ('X509_V_ERR_SUBJECT_ISSUER_MISMATCH',
|
| - 'subject issuer mismatch',
|
| - 'The current candidate issuer certificate was '
|
| - 'rejected because its subject name did not match '
|
| - 'the issuer name of the current certificate. Only '
|
| - 'displayed when the issuer_checks option is set.'),
|
| -
|
| - 30: ('X509_V_ERR_AKID_SKID_MISMATCH',
|
| - 'authority and subject key identifier mismatch',
|
| - 'The current candidate issuer certificate was '
|
| - 'rejected because its subject key identifier was '
|
| - 'present and did not match the authority key '
|
| - 'identifier current certificate. Only displayed '
|
| - 'when the issuer_checks option is set.'),
|
| -
|
| - 31: ('X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH',
|
| - 'authority and issuer serial number mismatch',
|
| - 'The current candidate issuer certificate was '
|
| - 'rejected because its issuer name and serial '
|
| - 'number was present and did not match the '
|
| - 'authority key identifier of the current '
|
| - 'certificate. Only displayed when the issuer_checks '
|
| - 'option is set.'),
|
| -
|
| - 32: ('X509_V_ERR_KEYUSAGE_NO_CERTSIGN',
|
| - 'key usage does not include certificate',
|
| - 'Signing the current candidate issuer certificate was '
|
| - 'rejected because its keyUsage extension does not '
|
| - 'permit certificate signing.'),
|
| -
|
| - 50: ('X509_V_ERR_APPLICATION_VERIFICATION',
|
| - 'application verification failure',
|
| - 'an application specific error. Unused.')}
|
| -
|
| -
|
| - def __init__(self, cert, errno, depth):
|
| - VerifyError.__init__(self, cert, errno, depth)
|
| - self.cert = cert
|
| - self.errno = errno
|
| - self.depth = depth
|
| -
|
| - def __repr__(self):
|
| - x = self._errorCodes.get(self.errno)
|
| - if x is not None:
|
| - name, short, long = x
|
| - return 'Peer Certificate Verification Failed: %s (error code: %d)' % (
|
| - long, self.errno
|
| - )
|
| - return "Peer Certificate Verification Failed for Unknown Reason"
|
| -
|
| - __str__ = __repr__
|
| -
|
| -
|
| -_x509names = {
|
| - 'CN': 'commonName',
|
| - 'commonName': 'commonName',
|
| -
|
| - 'O': 'organizationName',
|
| - 'organizationName': 'organizationName',
|
| -
|
| - 'OU': 'organizationalUnitName',
|
| - 'organizationalUnitName': 'organizationalUnitName',
|
| -
|
| - 'L': 'localityName',
|
| - 'localityName': 'localityName',
|
| -
|
| - 'ST': 'stateOrProvinceName',
|
| - 'stateOrProvinceName': 'stateOrProvinceName',
|
| -
|
| - 'C': 'countryName',
|
| - 'countryName': 'countryName',
|
| -
|
| - 'emailAddress': 'emailAddress'}
|
| -
|
| -
|
| -class DistinguishedName(dict):
|
| - """
|
| - Identify and describe an entity.
|
| -
|
| - Distinguished names are used to provide a minimal amount of identifying
|
| - information about a certificate issuer or subject. They are commonly
|
| - created with one or more of the following fields::
|
| -
|
| - commonName (CN)
|
| - organizationName (O)
|
| - organizationalUnitName (OU)
|
| - localityName (L)
|
| - stateOrProvinceName (ST)
|
| - countryName (C)
|
| - emailAddress
|
| - """
|
| - __slots__ = ()
|
| -
|
| - def __init__(self, **kw):
|
| - for k, v in kw.iteritems():
|
| - setattr(self, k, v)
|
| -
|
| -
|
| - def _copyFrom(self, x509name):
|
| - d = {}
|
| - for name in _x509names:
|
| - value = getattr(x509name, name, None)
|
| - if value is not None:
|
| - setattr(self, name, value)
|
| -
|
| -
|
| - def _copyInto(self, x509name):
|
| - for k, v in self.iteritems():
|
| - setattr(x509name, k, v)
|
| -
|
| -
|
| - def __repr__(self):
|
| - return '<DN %s>' % (dict.__repr__(self)[1:-1])
|
| -
|
| -
|
| - def __getattr__(self, attr):
|
| - try:
|
| - return self[_x509names[attr]]
|
| - except KeyError:
|
| - raise AttributeError(attr)
|
| -
|
| -
|
| - def __setattr__(self, attr, value):
|
| - assert type(attr) is str
|
| - if not attr in _x509names:
|
| - raise AttributeError("%s is not a valid OpenSSL X509 name field" % (attr,))
|
| - realAttr = _x509names[attr]
|
| - value = value.encode('ascii')
|
| - assert type(value) is str
|
| - self[realAttr] = value
|
| -
|
| -
|
| - def inspect(self):
|
| - """
|
| - Return a multi-line, human-readable representation of this DN.
|
| - """
|
| - l = []
|
| - lablen = 0
|
| - def uniqueValues(mapping):
|
| - return dict.fromkeys(mapping.itervalues()).keys()
|
| - for k in uniqueValues(_x509names):
|
| - label = util.nameToLabel(k)
|
| - lablen = max(len(label), lablen)
|
| - v = getattr(self, k, None)
|
| - if v is not None:
|
| - l.append((label, v))
|
| - lablen += 2
|
| - for n, (label, attr) in enumerate(l):
|
| - l[n] = (label.rjust(lablen)+': '+ attr)
|
| - return '\n'.join(l)
|
| -
|
| -DN = DistinguishedName
|
| -
|
| -
|
| -class CertBase:
|
| - def __init__(self, original):
|
| - self.original = original
|
| -
|
| - def _copyName(self, suffix):
|
| - dn = DistinguishedName()
|
| - dn._copyFrom(getattr(self.original, 'get_'+suffix)())
|
| - return dn
|
| -
|
| - def getSubject(self):
|
| - """
|
| - Retrieve the subject of this certificate.
|
| -
|
| - @rtype: L{DistinguishedName}
|
| - @return: A copy of the subject of this certificate.
|
| - """
|
| - return self._copyName('subject')
|
| -
|
| -
|
| -
|
| -def problemsFromTransport(tpt):
|
| - """
|
| - Retrieve the SSL errors associated with the given transport.
|
| -
|
| - @type tpt: L{ISystemHandle} provider wrapper around an SSL connection.
|
| - @rtype: C{list} of L{OpenSSLVerifyError}.
|
| - """
|
| - return tpt.getHandle().get_context().get_app_data().problems
|
| -
|
| -
|
| -def _handleattrhelper(Class, transport, methodName):
|
| - """
|
| - (private) Helper for L{Certificate.peerFromTransport} and
|
| - L{Certificate.hostFromTransport} which checks for incompatible handle types
|
| - and null certificates and raises the appropriate exception or returns the
|
| - appropriate certificate object.
|
| - """
|
| - method = getattr(transport.getHandle(),
|
| - "get_%s_certificate" % (methodName,), None)
|
| - if method is None:
|
| - raise CertificateError(
|
| - "non-TLS transport %r did not have %s certificate" % (transport, methodName))
|
| - cert = method()
|
| - if cert is None:
|
| - raise CertificateError(
|
| - "TLS transport %r did not have %s certificate" % (transport, methodName))
|
| - return Class(cert)
|
| -
|
| -
|
| -class Certificate(CertBase):
|
| - """
|
| - An x509 certificate.
|
| - """
|
| - def __repr__(self):
|
| - return '<%s Subject=%s Issuer=%s>' % (self.__class__.__name__,
|
| - self.getSubject().commonName,
|
| - self.getIssuer().commonName)
|
| -
|
| - def __eq__(self, other):
|
| - if isinstance(other, Certificate):
|
| - return self.dump() == other.dump()
|
| - return False
|
| -
|
| -
|
| - def __ne__(self, other):
|
| - return not self.__eq__(other)
|
| -
|
| -
|
| - def load(Class, requestData, format=crypto.FILETYPE_ASN1, args=()):
|
| - """
|
| - Load a certificate from an ASN.1- or PEM-format string.
|
| -
|
| - @rtype: C{Class}
|
| - """
|
| - return Class(crypto.load_certificate(format, requestData), *args)
|
| - load = classmethod(load)
|
| - _load = load
|
| -
|
| -
|
| - def dumpPEM(self):
|
| - """
|
| - Dump this certificate to a PEM-format data string.
|
| -
|
| - @rtype: C{str}
|
| - """
|
| - return self.dump(crypto.FILETYPE_PEM)
|
| -
|
| -
|
| - def loadPEM(Class, data):
|
| - """
|
| - Load a certificate from a PEM-format data string.
|
| -
|
| - @rtype: C{Class}
|
| - """
|
| - return Class.load(data, crypto.FILETYPE_PEM)
|
| - loadPEM = classmethod(loadPEM)
|
| -
|
| -
|
| - def peerFromTransport(Class, transport):
|
| - """
|
| - Get the certificate for the remote end of the given transport.
|
| -
|
| - @type: L{ISystemHandle}
|
| - @rtype: C{Class}
|
| -
|
| - @raise: L{CertificateError}, if the given transport does not have a peer
|
| - certificate.
|
| - """
|
| - return _handleattrhelper(Class, transport, 'peer')
|
| - peerFromTransport = classmethod(peerFromTransport)
|
| -
|
| -
|
| - def hostFromTransport(Class, transport):
|
| - """
|
| - Get the certificate for the local end of the given transport.
|
| -
|
| - @param transport: an L{ISystemHandle} provider; the transport we will
|
| -
|
| - @rtype: C{Class}
|
| -
|
| - @raise: L{CertificateError}, if the given transport does not have a host
|
| - certificate.
|
| - """
|
| - return _handleattrhelper(Class, transport, 'host')
|
| - hostFromTransport = classmethod(hostFromTransport)
|
| -
|
| -
|
| - def getPublicKey(self):
|
| - """
|
| - Get the public key for this certificate.
|
| -
|
| - @rtype: L{PublicKey}
|
| - """
|
| - return PublicKey(self.original.get_pubkey())
|
| -
|
| -
|
| - def dump(self, format=crypto.FILETYPE_ASN1):
|
| - return crypto.dump_certificate(format, self.original)
|
| -
|
| -
|
| - def serialNumber(self):
|
| - """
|
| - Retrieve the serial number of this certificate.
|
| -
|
| - @rtype: C{int}
|
| - """
|
| - return self.original.get_serial_number()
|
| -
|
| -
|
| - def digest(self, method='md5'):
|
| - """
|
| - Return a digest hash of this certificate using the specified hash
|
| - algorithm.
|
| -
|
| - @param method: One of C{'md5'} or C{'sha'}.
|
| - @rtype: C{str}
|
| - """
|
| - return self.original.digest(method)
|
| -
|
| -
|
| - def _inspect(self):
|
| - return '\n'.join(['Certificate For Subject:',
|
| - self.getSubject().inspect(),
|
| - '\nIssuer:',
|
| - self.getIssuer().inspect(),
|
| - '\nSerial Number: %d' % self.serialNumber(),
|
| - 'Digest: %s' % self.digest()])
|
| -
|
| -
|
| - def inspect(self):
|
| - """
|
| - Return a multi-line, human-readable representation of this
|
| - Certificate, including information about the subject, issuer, and
|
| - public key.
|
| - """
|
| - return '\n'.join((self._inspect(), self.getPublicKey().inspect()))
|
| -
|
| -
|
| - def getIssuer(self):
|
| - """
|
| - Retrieve the issuer of this certificate.
|
| -
|
| - @rtype: L{DistinguishedName}
|
| - @return: A copy of the issuer of this certificate.
|
| - """
|
| - return self._copyName('issuer')
|
| -
|
| -
|
| - def options(self, *authorities):
|
| - raise NotImplementedError('Possible, but doubtful we need this yet')
|
| -
|
| -
|
| -
|
| -class CertificateRequest(CertBase):
|
| - """
|
| - An x509 certificate request.
|
| -
|
| - Certificate requests are given to certificate authorities to be signed and
|
| - returned resulting in an actual certificate.
|
| - """
|
| - def load(Class, requestData, requestFormat=crypto.FILETYPE_ASN1):
|
| - req = crypto.load_certificate_request(requestFormat, requestData)
|
| - dn = DistinguishedName()
|
| - dn._copyFrom(req.get_subject())
|
| - if not req.verify(req.get_pubkey()):
|
| - raise VerifyError("Can't verify that request for %r is self-signed." % (dn,))
|
| - return Class(req)
|
| - load = classmethod(load)
|
| -
|
| -
|
| - def dump(self, format=crypto.FILETYPE_ASN1):
|
| - return crypto.dump_certificate_request(format, self.original)
|
| -
|
| -
|
| -
|
| -class PrivateCertificate(Certificate):
|
| - """
|
| - An x509 certificate and private key.
|
| - """
|
| - def __repr__(self):
|
| - return Certificate.__repr__(self) + ' with ' + repr(self.privateKey)
|
| -
|
| -
|
| - def _setPrivateKey(self, privateKey):
|
| - if not privateKey.matches(self.getPublicKey()):
|
| - raise VerifyError(
|
| - "Sanity check failed: Your certificate was not properly signed.")
|
| - self.privateKey = privateKey
|
| - return self
|
| -
|
| -
|
| - def newCertificate(self, newCertData, format=crypto.FILETYPE_ASN1):
|
| - """
|
| - Create a new L{PrivateCertificate} from the given certificate data and
|
| - this instance's private key.
|
| - """
|
| - return self.load(newCertData, self.privateKey, format)
|
| -
|
| -
|
| - def load(Class, data, privateKey, format=crypto.FILETYPE_ASN1):
|
| - return Class._load(data, format)._setPrivateKey(privateKey)
|
| - load = classmethod(load)
|
| -
|
| -
|
| - def inspect(self):
|
| - return '\n'.join([Certificate._inspect(self),
|
| - self.privateKey.inspect()])
|
| -
|
| -
|
| - def dumpPEM(self):
|
| - """
|
| - Dump both public and private parts of a private certificate to
|
| - PEM-format data.
|
| - """
|
| - return self.dump(crypto.FILETYPE_PEM) + self.privateKey.dump(crypto.FILETYPE_PEM)
|
| -
|
| -
|
| - def loadPEM(Class, data):
|
| - """
|
| - Load both private and public parts of a private certificate from a
|
| - chunk of PEM-format data.
|
| - """
|
| - return Class.load(data, KeyPair.load(data, crypto.FILETYPE_PEM),
|
| - crypto.FILETYPE_PEM)
|
| - loadPEM = classmethod(loadPEM)
|
| -
|
| -
|
| - def fromCertificateAndKeyPair(Class, certificateInstance, privateKey):
|
| - privcert = Class(certificateInstance.original)
|
| - return privcert._setPrivateKey(privateKey)
|
| - fromCertificateAndKeyPair = classmethod(fromCertificateAndKeyPair)
|
| -
|
| -
|
| - def options(self, *authorities):
|
| - options = dict(privateKey=self.privateKey.original,
|
| - certificate=self.original)
|
| - if authorities:
|
| - options.update(dict(verify=True,
|
| - requireCertificate=True,
|
| - caCerts=[auth.original for auth in authorities]))
|
| - return OpenSSLCertificateOptions(**options)
|
| -
|
| -
|
| - def certificateRequest(self, format=crypto.FILETYPE_ASN1,
|
| - digestAlgorithm='md5'):
|
| - return self.privateKey.certificateRequest(
|
| - self.getSubject(),
|
| - format,
|
| - digestAlgorithm)
|
| -
|
| -
|
| - def signCertificateRequest(self,
|
| - requestData,
|
| - verifyDNCallback,
|
| - serialNumber,
|
| - requestFormat=crypto.FILETYPE_ASN1,
|
| - certificateFormat=crypto.FILETYPE_ASN1):
|
| - issuer = self.getSubject()
|
| - return self.privateKey.signCertificateRequest(
|
| - issuer,
|
| - requestData,
|
| - verifyDNCallback,
|
| - serialNumber,
|
| - requestFormat,
|
| - certificateFormat)
|
| -
|
| -
|
| - def signRequestObject(self, certificateRequest, serialNumber,
|
| - secondsToExpiry=60 * 60 * 24 * 365, # One year
|
| - digestAlgorithm='md5'):
|
| - return self.privateKey.signRequestObject(self.getSubject(),
|
| - certificateRequest,
|
| - serialNumber,
|
| - secondsToExpiry,
|
| - digestAlgorithm)
|
| -
|
| -
|
| -class PublicKey:
|
| - def __init__(self, osslpkey):
|
| - self.original = osslpkey
|
| - req1 = crypto.X509Req()
|
| - req1.set_pubkey(osslpkey)
|
| - self._emptyReq = crypto.dump_certificate_request(crypto.FILETYPE_ASN1, req1)
|
| -
|
| -
|
| - def matches(self, otherKey):
|
| - return self._emptyReq == otherKey._emptyReq
|
| -
|
| -
|
| - # XXX This could be a useful method, but sometimes it triggers a segfault,
|
| - # so we'll steer clear for now.
|
| -# def verifyCertificate(self, certificate):
|
| -# """
|
| -# returns None, or raises a VerifyError exception if the certificate
|
| -# could not be verified.
|
| -# """
|
| -# if not certificate.original.verify(self.original):
|
| -# raise VerifyError("We didn't sign that certificate.")
|
| -
|
| - def __repr__(self):
|
| - return '<%s %s>' % (self.__class__.__name__, self.keyHash())
|
| -
|
| -
|
| - def keyHash(self):
|
| - """
|
| - MD5 hex digest of signature on an empty certificate request with this
|
| - key.
|
| - """
|
| - return hashlib.md5(self._emptyReq).hexdigest()
|
| -
|
| -
|
| - def inspect(self):
|
| - return 'Public Key with Hash: %s' % (self.keyHash(),)
|
| -
|
| -
|
| -
|
| -class KeyPair(PublicKey):
|
| -
|
| - def load(Class, data, format=crypto.FILETYPE_ASN1):
|
| - return Class(crypto.load_privatekey(format, data))
|
| - load = classmethod(load)
|
| -
|
| -
|
| - def dump(self, format=crypto.FILETYPE_ASN1):
|
| - return crypto.dump_privatekey(format, self.original)
|
| -
|
| -
|
| - def __getstate__(self):
|
| - return self.dump()
|
| -
|
| -
|
| - def __setstate__(self, state):
|
| - self.__init__(crypto.load_privatekey(crypto.FILETYPE_ASN1, state))
|
| -
|
| -
|
| - def inspect(self):
|
| - t = self.original.type()
|
| - if t == crypto.TYPE_RSA:
|
| - ts = 'RSA'
|
| - elif t == crypto.TYPE_DSA:
|
| - ts = 'DSA'
|
| - else:
|
| - ts = '(Unknown Type!)'
|
| - L = (self.original.bits(), ts, self.keyHash())
|
| - return '%s-bit %s Key Pair with Hash: %s' % L
|
| -
|
| -
|
| - def generate(Class, kind=crypto.TYPE_RSA, size=1024):
|
| - pkey = crypto.PKey()
|
| - pkey.generate_key(kind, size)
|
| - return Class(pkey)
|
| -
|
| -
|
| - def newCertificate(self, newCertData, format=crypto.FILETYPE_ASN1):
|
| - return PrivateCertificate.load(newCertData, self, format)
|
| - generate = classmethod(generate)
|
| -
|
| -
|
| - def requestObject(self, distinguishedName, digestAlgorithm='md5'):
|
| - req = crypto.X509Req()
|
| - req.set_pubkey(self.original)
|
| - distinguishedName._copyInto(req.get_subject())
|
| - req.sign(self.original, digestAlgorithm)
|
| - return CertificateRequest(req)
|
| -
|
| -
|
| - def certificateRequest(self, distinguishedName,
|
| - format=crypto.FILETYPE_ASN1,
|
| - digestAlgorithm='md5'):
|
| - """Create a certificate request signed with this key.
|
| -
|
| - @return: a string, formatted according to the 'format' argument.
|
| - """
|
| - return self.requestObject(distinguishedName, digestAlgorithm).dump(format)
|
| -
|
| -
|
| - def signCertificateRequest(self,
|
| - issuerDistinguishedName,
|
| - requestData,
|
| - verifyDNCallback,
|
| - serialNumber,
|
| - requestFormat=crypto.FILETYPE_ASN1,
|
| - certificateFormat=crypto.FILETYPE_ASN1,
|
| - secondsToExpiry=60 * 60 * 24 * 365, # One year
|
| - digestAlgorithm='md5'):
|
| - """
|
| - Given a blob of certificate request data and a certificate authority's
|
| - DistinguishedName, return a blob of signed certificate data.
|
| -
|
| - If verifyDNCallback returns a Deferred, I will return a Deferred which
|
| - fires the data when that Deferred has completed.
|
| - """
|
| - hlreq = CertificateRequest.load(requestData, requestFormat)
|
| -
|
| - dn = hlreq.getSubject()
|
| - vval = verifyDNCallback(dn)
|
| -
|
| - def verified(value):
|
| - if not value:
|
| - raise VerifyError("DN callback %r rejected request DN %r" % (verifyDNCallback, dn))
|
| - return self.signRequestObject(issuerDistinguishedName, hlreq,
|
| - serialNumber, secondsToExpiry, digestAlgorithm).dump(certificateFormat)
|
| -
|
| - if isinstance(vval, Deferred):
|
| - return vval.addCallback(verified)
|
| - else:
|
| - return verified(vval)
|
| -
|
| -
|
| - def signRequestObject(self,
|
| - issuerDistinguishedName,
|
| - requestObject,
|
| - serialNumber,
|
| - secondsToExpiry=60 * 60 * 24 * 365, # One year
|
| - digestAlgorithm='md5'):
|
| - """
|
| - Sign a CertificateRequest instance, returning a Certificate instance.
|
| - """
|
| - req = requestObject.original
|
| - dn = requestObject.getSubject()
|
| - cert = crypto.X509()
|
| - issuerDistinguishedName._copyInto(cert.get_issuer())
|
| - cert.set_subject(req.get_subject())
|
| - cert.set_pubkey(req.get_pubkey())
|
| - cert.gmtime_adj_notBefore(0)
|
| - cert.gmtime_adj_notAfter(secondsToExpiry)
|
| - cert.set_serial_number(serialNumber)
|
| - cert.sign(self.original, digestAlgorithm)
|
| - return Certificate(cert)
|
| -
|
| -
|
| - def selfSignedCert(self, serialNumber, **kw):
|
| - dn = DN(**kw)
|
| - return PrivateCertificate.fromCertificateAndKeyPair(
|
| - self.signRequestObject(dn, self.requestObject(dn), serialNumber),
|
| - self)
|
| -
|
| -
|
| -
|
| -class OpenSSLCertificateOptions(object):
|
| - """
|
| - A factory for SSL context objects for both SSL servers and clients.
|
| - """
|
| -
|
| - _context = None
|
| - # Older versions of PyOpenSSL didn't provide OP_ALL. Fudge it here, just in case.
|
| - _OP_ALL = getattr(SSL, 'OP_ALL', 0x0000FFFF)
|
| -
|
| - method = SSL.TLSv1_METHOD
|
| -
|
| - def __init__(self,
|
| - privateKey=None,
|
| - certificate=None,
|
| - method=None,
|
| - verify=False,
|
| - caCerts=None,
|
| - verifyDepth=9,
|
| - requireCertificate=True,
|
| - verifyOnce=True,
|
| - enableSingleUseKeys=True,
|
| - enableSessions=True,
|
| - fixBrokenPeers=False):
|
| - """
|
| - Create an OpenSSL context SSL connection context factory.
|
| -
|
| - @param privateKey: A PKey object holding the private key.
|
| -
|
| - @param certificate: An X509 object holding the certificate.
|
| -
|
| - @param method: The SSL protocol to use, one of SSLv23_METHOD,
|
| - SSLv2_METHOD, SSLv3_METHOD, TLSv1_METHOD. Defaults to TLSv1_METHOD.
|
| -
|
| - @param verify: If True, verify certificates received from the peer and
|
| - fail the handshake if verification fails. Otherwise, allow anonymous
|
| - sessions and sessions with certificates which fail validation. By
|
| - default this is False.
|
| -
|
| - @param caCerts: List of certificate authority certificates to
|
| - send to the client when requesting a certificate. Only used if verify
|
| - is True, and if verify is True, either this must be specified or
|
| - caCertsFile must be given. Since verify is False by default,
|
| - this is None by default.
|
| -
|
| - @param verifyDepth: Depth in certificate chain down to which to verify.
|
| - If unspecified, use the underlying default (9).
|
| -
|
| - @param requireCertificate: If True, do not allow anonymous sessions.
|
| -
|
| - @param verifyOnce: If True, do not re-verify the certificate
|
| - on session resumption.
|
| -
|
| - @param enableSingleUseKeys: If True, generate a new key whenever
|
| - ephemeral DH parameters are used to prevent small subgroup attacks.
|
| -
|
| - @param enableSessions: If True, set a session ID on each context. This
|
| - allows a shortened handshake to be used when a known client reconnects.
|
| -
|
| - @param fixBrokenPeers: If True, enable various non-spec protocol fixes
|
| - for broken SSL implementations. This should be entirely safe,
|
| - according to the OpenSSL documentation, but YMMV. This option is now
|
| - off by default, because it causes problems with connections between
|
| - peers using OpenSSL 0.9.8a.
|
| - """
|
| -
|
| - assert (privateKey is None) == (certificate is None), "Specify neither or both of privateKey and certificate"
|
| - self.privateKey = privateKey
|
| - self.certificate = certificate
|
| - if method is not None:
|
| - self.method = method
|
| -
|
| - self.verify = verify
|
| - assert ((verify and caCerts) or
|
| - (not verify)), "Specify client CA certificate information if and only if enabling certificate verification"
|
| -
|
| - self.caCerts = caCerts
|
| - self.verifyDepth = verifyDepth
|
| - self.requireCertificate = requireCertificate
|
| - self.verifyOnce = verifyOnce
|
| - self.enableSingleUseKeys = enableSingleUseKeys
|
| - self.enableSessions = enableSessions
|
| - self.fixBrokenPeers = fixBrokenPeers
|
| -
|
| -
|
| - def __getstate__(self):
|
| - d = self.__dict__.copy()
|
| - try:
|
| - del d['_context']
|
| - except KeyError:
|
| - pass
|
| - return d
|
| -
|
| -
|
| - def __setstate__(self, state):
|
| - self.__dict__ = state
|
| -
|
| -
|
| - def getContext(self):
|
| - """Return a SSL.Context object.
|
| - """
|
| - if self._context is None:
|
| - self._context = self._makeContext()
|
| - return self._context
|
| -
|
| -
|
| - def _makeContext(self):
|
| - ctx = SSL.Context(self.method)
|
| - ctx.set_app_data(_SSLApplicationData())
|
| -
|
| - if self.certificate is not None and self.privateKey is not None:
|
| - ctx.use_certificate(self.certificate)
|
| - ctx.use_privatekey(self.privateKey)
|
| - # Sanity check
|
| - ctx.check_privatekey()
|
| -
|
| - verifyFlags = SSL.VERIFY_NONE
|
| - if self.verify:
|
| - verifyFlags = SSL.VERIFY_PEER
|
| - if self.requireCertificate:
|
| - verifyFlags |= SSL.VERIFY_FAIL_IF_NO_PEER_CERT
|
| - if self.verifyOnce:
|
| - verifyFlags |= SSL.VERIFY_CLIENT_ONCE
|
| - if self.caCerts:
|
| - store = ctx.get_cert_store()
|
| - for cert in self.caCerts:
|
| - store.add_cert(cert)
|
| -
|
| - def _trackVerificationProblems(conn,cert,errno,depth,preverify_ok):
|
| - # retcode is the answer OpenSSL's default verifier would have
|
| - # given, had we allowed it to run.
|
| - if not preverify_ok:
|
| - ctx.get_app_data().problems.append(OpenSSLVerifyError(cert, errno, depth))
|
| - return preverify_ok
|
| - ctx.set_verify(verifyFlags, _trackVerificationProblems)
|
| -
|
| - if self.verifyDepth is not None:
|
| - ctx.set_verify_depth(self.verifyDepth)
|
| -
|
| - if self.enableSingleUseKeys:
|
| - ctx.set_options(SSL.OP_SINGLE_DH_USE)
|
| -
|
| - if self.fixBrokenPeers:
|
| - ctx.set_options(self._OP_ALL)
|
| -
|
| - if self.enableSessions:
|
| - sessionName = hashlib.md5("%s-%d" % (reflect.qual(self.__class__), _sessionCounter())).hexdigest()
|
| - ctx.set_session_id(sessionName)
|
| -
|
| - return ctx
|
|
|