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)
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)