示例#1
0
def _load_certificate_data(certtype, buffer, result_typeid):
    """
    Load a certificate with the supplied type and data.

    @param certtype: ignored
    @type certtype: -
    @param buffer: name of the KeyChain item to lookup
    @type buffer: L{str}
    @param result_typeid: The type to return (certificate or key)
    @type result_typeid: L{ffi.CFTypeID}

    @return: the certificate
    @rtype: L{X509}
    """

    # First try to get the identity from the KeyChain
    data = CFDataRef.fromString(buffer)
    results = ffi.new("CFArrayRef *")
    err = security.SecItemImport(data.ref(), ffi.NULL, ffi.NULL, ffi.NULL, 0,
                                 ffi.NULL, ffi.NULL, results)
    if err != 0:
        raise Error("Could not load certificate data")

    results = CFArrayRef(results[0]).toList()

    # Try to find a SecCertificateRef
    for result in results:
        if result.instanceTypeId() == result_typeid:
            return result
    else:
        raise Error("No certificate in data")
示例#2
0
    def connect(self):
        """
        Create the SecureTransport SSLContextRef object and initialize it.
        """

        self.ctx = security.SSLCreateContext(ffi.NULL, security.kSSLClientSide if self.is_client else security.kSSLServerSide, security.kSSLStreamType)

        minVersion = None
        for option, minValue in (
            (OP_NO_SSLv2, security.kSSLProtocol3),
            (OP_NO_SSLv3, security.kTLSProtocol1),
            (OP_NO_TLSv1, security.kTLSProtocol11),
            (OP_NO_TLSv1_1, security.kTLSProtocol12),
            (OP_NO_TLSv1_2, security.kTLSProtocol12),   # TLS1.2 is the highest supported right now
        ):
            if option in self.context.options:
                minVersion = minValue
        if minVersion is not None:
            security.SSLSetProtocolVersionMin(self.ctx, minVersion)

        # Make sure we have a reference back to this L{Connection} in the SecureTransport callbacks
        self.connref = ffi.new("int *", self.engine_id)
        err = security.SSLSetConnection(self.ctx, ffi.cast("SSLConnectionRef", self.connref))
        if err:
            self.shutdown()
            raise Error(err)

        # Setup the actual SecureTransport callbacks
        err = security.SSLSetIOFuncs(self.ctx, self._read, self._write)
        if err:
            self.shutdown()
            raise Error(err)

        # Must have a certificate identity if we are a server
        if not self.is_client and self.context.identity is None:
            self.shutdown()
            raise Error("No certificate")

        # Must have a peer name if we are a client
        if self.is_client and not self.context.peerName:
            self.shutdown()
            raise Error("No peer name set with client connection.")
        elif self.is_client:
            # Always set the client peer name for proper certificate validation
            err = security.SSLSetPeerDomainName(self.ctx, self.context.peerName, len(self.context.peerName))
            if err:
                self.shutdown()
                raise Error(err)

        # Add the certificate
        if self.context.identity is not None:
            certs = CFArrayRef.fromList([self.context.identity])
            err = security.SSLSetCertificate(self.ctx, certs.ref())
            if err:
                self.shutdown()
                raise Error(err)
示例#3
0
def load_keychain_identity(identity):
    """
    Retrieve a SecIdentityRef from the KeyChain with a identity that exactly matches the passed in value.

    @param identity: identity value to match
    @type identity: L{str}

    @return: matched SecIdentityRef item or L{None}
    @rtype: L{CFObjectRef}
    """

    # First try to load this from an identity preference
    cfsubject = CFStringRef.fromString(identity)
    secidentity = security.SecIdentityCopyPreferred(cfsubject.ref(), ffi.NULL,
                                                    ffi.NULL)
    if secidentity != ffi.NULL:
        return CFObjectRef(secidentity)

    # Now iterate items to find a match
    match = CFDictionaryRef.fromDict({
        CFStringRef.fromRef(security.kSecClass):
        CFStringRef.fromRef(security.kSecClassIdentity),
        CFStringRef.fromRef(security.kSecReturnRef):
        CFBooleanRef.fromBool(True),
        CFStringRef.fromRef(security.kSecReturnAttributes):
        CFBooleanRef.fromBool(True),
        CFStringRef.fromRef(security.kSecMatchLimit):
        CFStringRef.fromRef(security.kSecMatchLimitAll),
    })
    result = ffi.new("CFTypeRef *")
    err = security.SecItemCopyMatching(match.ref(), result)
    if err != 0:
        return None

    result = CFArrayRef(result[0])
    for item in result.toList():
        if item[str(CFStringRef.fromRef(security.kSecAttrLabel))] == identity:
            secidentity = item[str(CFStringRef.fromRef(security.kSecValueRef))]
            break
    else:
        raise Error("Could not find Keychain identity: {}".format(identity))

    return secidentity
示例#4
0
    def get_subject(self):
        """
        Use Security.framework to extract the componentized SubjectName field and map OID
        values to strings and store in an L{X509Name} object.
        """
        keys = CFArrayRef.fromList(
            [CFStringRef.fromRef(security.kSecOIDX509V1SubjectName)])
        error = ffi.new("CFErrorRef *")
        values = security.SecCertificateCopyValues(self._x509.ref(),
                                                   keys.ref(), error)
        if values == ffi.NULL:
            error = CFErrorRef(error[0])
            raise Error("Unable to get certificate subject")
        values = CFDictionaryRef(values).toDict()
        value = values[str(
            CFStringRef.fromRef(security.kSecOIDX509V1SubjectName))]

        components = {}
        if value[str(CFStringRef.fromRef(
                security.kSecPropertyKeyType))] == str(
                    CFStringRef.fromRef(security.kSecPropertyTypeSection)):
            for item in value[str(
                    CFStringRef.fromRef(security.kSecPropertyKeyValue))]:
                if item[str(CFStringRef.fromRef(
                        security.kSecPropertyKeyType))] == str(
                            CFStringRef.fromRef(
                                security.kSecPropertyTypeString)):
                    v = item[str(
                        CFStringRef.fromRef(security.kSecPropertyKeyValue))]
                    k = OID2STR.get(
                        item[str(
                            CFStringRef.fromRef(
                                security.kSecPropertyKeyLabel))], "Unknown")
                    components[k] = v

        return X509Name("Subject Name", components)