diff options
Diffstat (limited to 'Swiften/TLS/OpenSSL')
-rw-r--r-- | Swiften/TLS/OpenSSL/OpenSSLCertificate.cpp | 140 | ||||
-rw-r--r-- | Swiften/TLS/OpenSSL/OpenSSLCertificate.h | 108 | ||||
-rw-r--r-- | Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.h | 12 | ||||
-rw-r--r-- | Swiften/TLS/OpenSSL/OpenSSLContext.cpp | 496 | ||||
-rw-r--r-- | Swiften/TLS/OpenSSL/OpenSSLContext.h | 50 | ||||
-rw-r--r-- | Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp | 18 | ||||
-rw-r--r-- | Swiften/TLS/OpenSSL/OpenSSLContextFactory.h | 16 |
7 files changed, 420 insertions, 420 deletions
diff --git a/Swiften/TLS/OpenSSL/OpenSSLCertificate.cpp b/Swiften/TLS/OpenSSL/OpenSSLCertificate.cpp index fc8dce5..3110813 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLCertificate.cpp +++ b/Swiften/TLS/OpenSSL/OpenSSLCertificate.cpp @@ -20,91 +20,91 @@ namespace Swift { OpenSSLCertificate::OpenSSLCertificate(boost::shared_ptr<X509> cert) : cert(cert) { - parse(); + parse(); } OpenSSLCertificate::OpenSSLCertificate(const ByteArray& der) { #if OPENSSL_VERSION_NUMBER <= 0x009070cfL - unsigned char* p = const_cast<unsigned char*>(vecptr(der)); + unsigned char* p = const_cast<unsigned char*>(vecptr(der)); #else - const unsigned char* p = vecptr(der); + const unsigned char* p = vecptr(der); #endif - cert = boost::shared_ptr<X509>(d2i_X509(NULL, &p, der.size()), X509_free); - if (!cert) { - SWIFT_LOG(warning) << "Error creating certificate from DER data" << std::endl; - } - parse(); + cert = boost::shared_ptr<X509>(d2i_X509(NULL, &p, der.size()), X509_free); + if (!cert) { + SWIFT_LOG(warning) << "Error creating certificate from DER data" << std::endl; + } + parse(); } ByteArray OpenSSLCertificate::toDER() const { - ByteArray result; - if (!cert) { - return result; - } - result.resize(i2d_X509(cert.get(), NULL)); - unsigned char* p = vecptr(result); - i2d_X509(cert.get(), &p); - return result; + ByteArray result; + if (!cert) { + return result; + } + result.resize(i2d_X509(cert.get(), NULL)); + unsigned char* p = vecptr(result); + i2d_X509(cert.get(), &p); + return result; } void OpenSSLCertificate::parse() { - if (!cert) { - return; - } - // Subject name - X509_NAME* subjectName = X509_get_subject_name(cert.get()); - if (subjectName) { - // Subject name - ByteArray subjectNameData; - subjectNameData.resize(256); - X509_NAME_oneline(X509_get_subject_name(cert.get()), reinterpret_cast<char*>(vecptr(subjectNameData)), static_cast<unsigned int>(subjectNameData.size())); - this->subjectName = byteArrayToString(subjectNameData); + if (!cert) { + return; + } + // Subject name + X509_NAME* subjectName = X509_get_subject_name(cert.get()); + if (subjectName) { + // Subject name + ByteArray subjectNameData; + subjectNameData.resize(256); + X509_NAME_oneline(X509_get_subject_name(cert.get()), reinterpret_cast<char*>(vecptr(subjectNameData)), static_cast<unsigned int>(subjectNameData.size())); + this->subjectName = byteArrayToString(subjectNameData); - // Common name - int cnLoc = X509_NAME_get_index_by_NID(subjectName, NID_commonName, -1); - while (cnLoc != -1) { - X509_NAME_ENTRY* cnEntry = X509_NAME_get_entry(subjectName, cnLoc); - ASN1_STRING* cnData = X509_NAME_ENTRY_get_data(cnEntry); - commonNames.push_back(byteArrayToString(createByteArray(reinterpret_cast<const char*>(cnData->data), cnData->length))); - cnLoc = X509_NAME_get_index_by_NID(subjectName, NID_commonName, cnLoc); - } - } + // Common name + int cnLoc = X509_NAME_get_index_by_NID(subjectName, NID_commonName, -1); + while (cnLoc != -1) { + X509_NAME_ENTRY* cnEntry = X509_NAME_get_entry(subjectName, cnLoc); + ASN1_STRING* cnData = X509_NAME_ENTRY_get_data(cnEntry); + commonNames.push_back(byteArrayToString(createByteArray(reinterpret_cast<const char*>(cnData->data), cnData->length))); + cnLoc = X509_NAME_get_index_by_NID(subjectName, NID_commonName, cnLoc); + } + } - // subjectAltNames - int subjectAltNameLoc = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1); - if(subjectAltNameLoc != -1) { - X509_EXTENSION* extension = X509_get_ext(cert.get(), subjectAltNameLoc); - boost::shared_ptr<GENERAL_NAMES> generalNames(reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(extension)), GENERAL_NAMES_free); - boost::shared_ptr<ASN1_OBJECT> xmppAddrObject(OBJ_txt2obj(ID_ON_XMPPADDR_OID, 1), ASN1_OBJECT_free); - boost::shared_ptr<ASN1_OBJECT> dnsSRVObject(OBJ_txt2obj(ID_ON_DNSSRV_OID, 1), ASN1_OBJECT_free); - for (int i = 0; i < sk_GENERAL_NAME_num(generalNames.get()); ++i) { - GENERAL_NAME* generalName = sk_GENERAL_NAME_value(generalNames.get(), i); - if (generalName->type == GEN_OTHERNAME) { - OTHERNAME* otherName = generalName->d.otherName; - if (OBJ_cmp(otherName->type_id, xmppAddrObject.get()) == 0) { - // XmppAddr - if (otherName->value->type != V_ASN1_UTF8STRING) { - continue; - } - ASN1_UTF8STRING* xmppAddrValue = otherName->value->value.utf8string; - addXMPPAddress(byteArrayToString(createByteArray(reinterpret_cast<const char*>(ASN1_STRING_data(xmppAddrValue)), ASN1_STRING_length(xmppAddrValue)))); - } - else if (OBJ_cmp(otherName->type_id, dnsSRVObject.get()) == 0) { - // SRVName - if (otherName->value->type != V_ASN1_IA5STRING) { - continue; - } - ASN1_IA5STRING* srvNameValue = otherName->value->value.ia5string; - addSRVName(byteArrayToString(createByteArray(reinterpret_cast<const char*>(ASN1_STRING_data(srvNameValue)), ASN1_STRING_length(srvNameValue)))); - } - } - else if (generalName->type == GEN_DNS) { - // DNSName - addDNSName(byteArrayToString(createByteArray(ASN1_STRING_data(generalName->d.dNSName), ASN1_STRING_length(generalName->d.dNSName)))); - } - } - } + // subjectAltNames + int subjectAltNameLoc = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1); + if(subjectAltNameLoc != -1) { + X509_EXTENSION* extension = X509_get_ext(cert.get(), subjectAltNameLoc); + boost::shared_ptr<GENERAL_NAMES> generalNames(reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(extension)), GENERAL_NAMES_free); + boost::shared_ptr<ASN1_OBJECT> xmppAddrObject(OBJ_txt2obj(ID_ON_XMPPADDR_OID, 1), ASN1_OBJECT_free); + boost::shared_ptr<ASN1_OBJECT> dnsSRVObject(OBJ_txt2obj(ID_ON_DNSSRV_OID, 1), ASN1_OBJECT_free); + for (int i = 0; i < sk_GENERAL_NAME_num(generalNames.get()); ++i) { + GENERAL_NAME* generalName = sk_GENERAL_NAME_value(generalNames.get(), i); + if (generalName->type == GEN_OTHERNAME) { + OTHERNAME* otherName = generalName->d.otherName; + if (OBJ_cmp(otherName->type_id, xmppAddrObject.get()) == 0) { + // XmppAddr + if (otherName->value->type != V_ASN1_UTF8STRING) { + continue; + } + ASN1_UTF8STRING* xmppAddrValue = otherName->value->value.utf8string; + addXMPPAddress(byteArrayToString(createByteArray(reinterpret_cast<const char*>(ASN1_STRING_data(xmppAddrValue)), ASN1_STRING_length(xmppAddrValue)))); + } + else if (OBJ_cmp(otherName->type_id, dnsSRVObject.get()) == 0) { + // SRVName + if (otherName->value->type != V_ASN1_IA5STRING) { + continue; + } + ASN1_IA5STRING* srvNameValue = otherName->value->value.ia5string; + addSRVName(byteArrayToString(createByteArray(reinterpret_cast<const char*>(ASN1_STRING_data(srvNameValue)), ASN1_STRING_length(srvNameValue)))); + } + } + else if (generalName->type == GEN_DNS) { + // DNSName + addDNSName(byteArrayToString(createByteArray(ASN1_STRING_data(generalName->d.dNSName), ASN1_STRING_length(generalName->d.dNSName)))); + } + } + } } } diff --git a/Swiften/TLS/OpenSSL/OpenSSLCertificate.h b/Swiften/TLS/OpenSSL/OpenSSLCertificate.h index 7419849..4b8b32c 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLCertificate.h +++ b/Swiften/TLS/OpenSSL/OpenSSLCertificate.h @@ -15,58 +15,58 @@ #include <Swiften/TLS/Certificate.h> namespace Swift { - class OpenSSLCertificate : public Certificate { - public: - OpenSSLCertificate(boost::shared_ptr<X509>); - OpenSSLCertificate(const ByteArray& der); - - std::string getSubjectName() const { - return subjectName; - } - - std::vector<std::string> getCommonNames() const { - return commonNames; - } - - std::vector<std::string> getSRVNames() const { - return srvNames; - } - - std::vector<std::string> getDNSNames() const { - return dnsNames; - } - - std::vector<std::string> getXMPPAddresses() const { - return xmppAddresses; - } - - ByteArray toDER() const; - - boost::shared_ptr<X509> getInternalX509() const { - return cert; - } - - private: - void parse(); - - void addSRVName(const std::string& name) { - srvNames.push_back(name); - } - - void addDNSName(const std::string& name) { - dnsNames.push_back(name); - } - - void addXMPPAddress(const std::string& addr) { - xmppAddresses.push_back(addr); - } - - private: - boost::shared_ptr<X509> cert; - std::string subjectName; - std::vector<std::string> commonNames; - std::vector<std::string> dnsNames; - std::vector<std::string> xmppAddresses; - std::vector<std::string> srvNames; - }; + class OpenSSLCertificate : public Certificate { + public: + OpenSSLCertificate(boost::shared_ptr<X509>); + OpenSSLCertificate(const ByteArray& der); + + std::string getSubjectName() const { + return subjectName; + } + + std::vector<std::string> getCommonNames() const { + return commonNames; + } + + std::vector<std::string> getSRVNames() const { + return srvNames; + } + + std::vector<std::string> getDNSNames() const { + return dnsNames; + } + + std::vector<std::string> getXMPPAddresses() const { + return xmppAddresses; + } + + ByteArray toDER() const; + + boost::shared_ptr<X509> getInternalX509() const { + return cert; + } + + private: + void parse(); + + void addSRVName(const std::string& name) { + srvNames.push_back(name); + } + + void addDNSName(const std::string& name) { + dnsNames.push_back(name); + } + + void addXMPPAddress(const std::string& addr) { + xmppAddresses.push_back(addr); + } + + private: + boost::shared_ptr<X509> cert; + std::string subjectName; + std::vector<std::string> commonNames; + std::vector<std::string> dnsNames; + std::vector<std::string> xmppAddresses; + std::vector<std::string> srvNames; + }; } diff --git a/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.h b/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.h index bb8780e..c996cd5 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.h +++ b/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.h @@ -10,10 +10,10 @@ #include <Swiften/TLS/OpenSSL/OpenSSLCertificate.h> namespace Swift { - class OpenSSLCertificateFactory : public CertificateFactory { - public: - virtual Certificate* createCertificateFromDER(const ByteArray& der) { - return new OpenSSLCertificate(der); - } - }; + class OpenSSLCertificateFactory : public CertificateFactory { + public: + virtual Certificate* createCertificateFromDER(const ByteArray& der) { + return new OpenSSLCertificate(der); + } + }; } diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp index a3e0e1d..cc420e6 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp +++ b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp @@ -36,302 +36,302 @@ static const int MAX_FINISHED_SIZE = 4096; static const int SSL_READ_BUFFERSIZE = 8192; static void freeX509Stack(STACK_OF(X509)* stack) { - sk_X509_free(stack); + sk_X509_free(stack); } OpenSSLContext::OpenSSLContext() : state_(Start), context_(0), handle_(0), readBIO_(0), writeBIO_(0) { - ensureLibraryInitialized(); - context_ = SSL_CTX_new(SSLv23_client_method()); - SSL_CTX_set_options(context_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + ensureLibraryInitialized(); + context_ = SSL_CTX_new(SSLv23_client_method()); + SSL_CTX_set_options(context_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); - // TODO: implement CRL checking - // TODO: download CRL (HTTP transport) - // TODO: cache CRL downloads for configurable time period + // TODO: implement CRL checking + // TODO: download CRL (HTTP transport) + // TODO: cache CRL downloads for configurable time period - // TODO: implement OCSP support - // TODO: handle OCSP stapling see https://www.rfc-editor.org/rfc/rfc4366.txt - // Load system certs + // TODO: implement OCSP support + // TODO: handle OCSP stapling see https://www.rfc-editor.org/rfc/rfc4366.txt + // Load system certs #if defined(SWIFTEN_PLATFORM_WINDOWS) - X509_STORE* store = SSL_CTX_get_cert_store(context_); - HCERTSTORE systemStore = CertOpenSystemStore(0, "ROOT"); - if (systemStore) { - PCCERT_CONTEXT certContext = NULL; - while (true) { - certContext = CertFindCertificateInStore(systemStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, certContext); - if (!certContext) { - break; - } - OpenSSLCertificate cert(createByteArray(certContext->pbCertEncoded, certContext->cbCertEncoded)); - if (store && cert.getInternalX509()) { - X509_STORE_add_cert(store, cert.getInternalX509().get()); - } - } - } + X509_STORE* store = SSL_CTX_get_cert_store(context_); + HCERTSTORE systemStore = CertOpenSystemStore(0, "ROOT"); + if (systemStore) { + PCCERT_CONTEXT certContext = NULL; + while (true) { + certContext = CertFindCertificateInStore(systemStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, certContext); + if (!certContext) { + break; + } + OpenSSLCertificate cert(createByteArray(certContext->pbCertEncoded, certContext->cbCertEncoded)); + if (store && cert.getInternalX509()) { + X509_STORE_add_cert(store, cert.getInternalX509().get()); + } + } + } #elif !defined(SWIFTEN_PLATFORM_MACOSX) - SSL_CTX_load_verify_locations(context_, NULL, "/etc/ssl/certs"); + SSL_CTX_load_verify_locations(context_, NULL, "/etc/ssl/certs"); #elif defined(SWIFTEN_PLATFORM_MACOSX) && !defined(SWIFTEN_PLATFORM_IPHONE) - // On Mac OS X 10.5 (OpenSSL < 0.9.8), OpenSSL does not automatically look in the system store. - // On Mac OS X 10.6 (OpenSSL >= 0.9.8), OpenSSL *does* look in the system store to determine trust. - // However, if there is a certificate error, it will always emit the "Invalid CA" error if we didn't add - // the certificates first. See - // http://opensource.apple.com/source/OpenSSL098/OpenSSL098-27/src/crypto/x509/x509_vfy_apple.c - // to understand why. We therefore add all certs from the system store ourselves. - X509_STORE* store = SSL_CTX_get_cert_store(context_); - CFArrayRef anchorCertificates; - if (SecTrustCopyAnchorCertificates(&anchorCertificates) == 0) { - for (int i = 0; i < CFArrayGetCount(anchorCertificates); ++i) { - SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(const_cast<void*>(CFArrayGetValueAtIndex(anchorCertificates, i))); - CSSM_DATA certCSSMData; - if (SecCertificateGetData(cert, &certCSSMData) != 0 || certCSSMData.Length == 0) { - continue; - } - std::vector<unsigned char> certData; - certData.resize(certCSSMData.Length); - memcpy(&certData[0], certCSSMData.Data, certCSSMData.Length); - OpenSSLCertificate certificate(certData); - if (store && certificate.getInternalX509()) { - X509_STORE_add_cert(store, certificate.getInternalX509().get()); - } - } - CFRelease(anchorCertificates); - } + // On Mac OS X 10.5 (OpenSSL < 0.9.8), OpenSSL does not automatically look in the system store. + // On Mac OS X 10.6 (OpenSSL >= 0.9.8), OpenSSL *does* look in the system store to determine trust. + // However, if there is a certificate error, it will always emit the "Invalid CA" error if we didn't add + // the certificates first. See + // http://opensource.apple.com/source/OpenSSL098/OpenSSL098-27/src/crypto/x509/x509_vfy_apple.c + // to understand why. We therefore add all certs from the system store ourselves. + X509_STORE* store = SSL_CTX_get_cert_store(context_); + CFArrayRef anchorCertificates; + if (SecTrustCopyAnchorCertificates(&anchorCertificates) == 0) { + for (int i = 0; i < CFArrayGetCount(anchorCertificates); ++i) { + SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(const_cast<void*>(CFArrayGetValueAtIndex(anchorCertificates, i))); + CSSM_DATA certCSSMData; + if (SecCertificateGetData(cert, &certCSSMData) != 0 || certCSSMData.Length == 0) { + continue; + } + std::vector<unsigned char> certData; + certData.resize(certCSSMData.Length); + memcpy(&certData[0], certCSSMData.Data, certCSSMData.Length); + OpenSSLCertificate certificate(certData); + if (store && certificate.getInternalX509()) { + X509_STORE_add_cert(store, certificate.getInternalX509().get()); + } + } + CFRelease(anchorCertificates); + } #endif } OpenSSLContext::~OpenSSLContext() { - SSL_free(handle_); - SSL_CTX_free(context_); + SSL_free(handle_); + SSL_CTX_free(context_); } void OpenSSLContext::ensureLibraryInitialized() { - static bool isLibraryInitialized = false; - if (!isLibraryInitialized) { - SSL_load_error_strings(); - SSL_library_init(); - OpenSSL_add_all_algorithms(); - - // Disable compression - /* - STACK_OF(SSL_COMP)* compressionMethods = SSL_COMP_get_compression_methods(); - sk_SSL_COMP_zero(compressionMethods);*/ - - isLibraryInitialized = true; - } + static bool isLibraryInitialized = false; + if (!isLibraryInitialized) { + SSL_load_error_strings(); + SSL_library_init(); + OpenSSL_add_all_algorithms(); + + // Disable compression + /* + STACK_OF(SSL_COMP)* compressionMethods = SSL_COMP_get_compression_methods(); + sk_SSL_COMP_zero(compressionMethods);*/ + + isLibraryInitialized = true; + } } void OpenSSLContext::connect() { - handle_ = SSL_new(context_); - // Ownership of BIOs is ransferred - readBIO_ = BIO_new(BIO_s_mem()); - writeBIO_ = BIO_new(BIO_s_mem()); - SSL_set_bio(handle_, readBIO_, writeBIO_); - - state_ = Connecting; - doConnect(); + handle_ = SSL_new(context_); + // Ownership of BIOs is ransferred + readBIO_ = BIO_new(BIO_s_mem()); + writeBIO_ = BIO_new(BIO_s_mem()); + SSL_set_bio(handle_, readBIO_, writeBIO_); + + state_ = Connecting; + doConnect(); } void OpenSSLContext::doConnect() { - int connectResult = SSL_connect(handle_); - int error = SSL_get_error(handle_, connectResult); - switch (error) { - case SSL_ERROR_NONE: { - state_ = Connected; - //std::cout << x->name << std::endl; - //const char* comp = SSL_get_current_compression(handle_); - //std::cout << "Compression: " << SSL_COMP_get_name(comp) << std::endl; - onConnected(); - break; - } - case SSL_ERROR_WANT_READ: - sendPendingDataToNetwork(); - break; - default: - state_ = Error; - onError(boost::make_shared<TLSError>()); - } + int connectResult = SSL_connect(handle_); + int error = SSL_get_error(handle_, connectResult); + switch (error) { + case SSL_ERROR_NONE: { + state_ = Connected; + //std::cout << x->name << std::endl; + //const char* comp = SSL_get_current_compression(handle_); + //std::cout << "Compression: " << SSL_COMP_get_name(comp) << std::endl; + onConnected(); + break; + } + case SSL_ERROR_WANT_READ: + sendPendingDataToNetwork(); + break; + default: + state_ = Error; + onError(boost::make_shared<TLSError>()); + } } void OpenSSLContext::sendPendingDataToNetwork() { - int size = BIO_pending(writeBIO_); - if (size > 0) { - SafeByteArray data; - data.resize(size); - BIO_read(writeBIO_, vecptr(data), size); - onDataForNetwork(data); - } + int size = BIO_pending(writeBIO_); + if (size > 0) { + SafeByteArray data; + data.resize(size); + BIO_read(writeBIO_, vecptr(data), size); + onDataForNetwork(data); + } } void OpenSSLContext::handleDataFromNetwork(const SafeByteArray& data) { - BIO_write(readBIO_, vecptr(data), data.size()); - switch (state_) { - case Connecting: - doConnect(); - break; - case Connected: - sendPendingDataToApplication(); - break; - case Start: assert(false); break; - case Error: /*assert(false);*/ break; - } + BIO_write(readBIO_, vecptr(data), data.size()); + switch (state_) { + case Connecting: + doConnect(); + break; + case Connected: + sendPendingDataToApplication(); + break; + case Start: assert(false); break; + case Error: /*assert(false);*/ break; + } } void OpenSSLContext::handleDataFromApplication(const SafeByteArray& data) { - if (SSL_write(handle_, vecptr(data), data.size()) >= 0) { - sendPendingDataToNetwork(); - } - else { - state_ = Error; - onError(boost::make_shared<TLSError>()); - } + if (SSL_write(handle_, vecptr(data), data.size()) >= 0) { + sendPendingDataToNetwork(); + } + else { + state_ = Error; + onError(boost::make_shared<TLSError>()); + } } void OpenSSLContext::sendPendingDataToApplication() { - SafeByteArray data; - data.resize(SSL_READ_BUFFERSIZE); - int ret = SSL_read(handle_, vecptr(data), data.size()); - while (ret > 0) { - data.resize(ret); - onDataForApplication(data); - data.resize(SSL_READ_BUFFERSIZE); - ret = SSL_read(handle_, vecptr(data), data.size()); - } - if (ret < 0 && SSL_get_error(handle_, ret) != SSL_ERROR_WANT_READ) { - state_ = Error; - onError(boost::make_shared<TLSError>()); - } + SafeByteArray data; + data.resize(SSL_READ_BUFFERSIZE); + int ret = SSL_read(handle_, vecptr(data), data.size()); + while (ret > 0) { + data.resize(ret); + onDataForApplication(data); + data.resize(SSL_READ_BUFFERSIZE); + ret = SSL_read(handle_, vecptr(data), data.size()); + } + if (ret < 0 && SSL_get_error(handle_, ret) != SSL_ERROR_WANT_READ) { + state_ = Error; + onError(boost::make_shared<TLSError>()); + } } bool OpenSSLContext::setClientCertificate(CertificateWithKey::ref certificate) { - boost::shared_ptr<PKCS12Certificate> pkcs12Certificate = boost::dynamic_pointer_cast<PKCS12Certificate>(certificate); - if (!pkcs12Certificate || pkcs12Certificate->isNull()) { - return false; - } - - // Create a PKCS12 structure - BIO* bio = BIO_new(BIO_s_mem()); - BIO_write(bio, vecptr(pkcs12Certificate->getData()), pkcs12Certificate->getData().size()); - boost::shared_ptr<PKCS12> pkcs12(d2i_PKCS12_bio(bio, NULL), PKCS12_free); - BIO_free(bio); - if (!pkcs12) { - return false; - } - - // Parse PKCS12 - X509 *certPtr = 0; - EVP_PKEY* privateKeyPtr = 0; - STACK_OF(X509)* caCertsPtr = 0; - SafeByteArray password(pkcs12Certificate->getPassword()); - password.push_back(0); - int result = PKCS12_parse(pkcs12.get(), reinterpret_cast<const char*>(vecptr(password)), &privateKeyPtr, &certPtr, &caCertsPtr); - if (result != 1) { - return false; - } - boost::shared_ptr<X509> cert(certPtr, X509_free); - boost::shared_ptr<EVP_PKEY> privateKey(privateKeyPtr, EVP_PKEY_free); - boost::shared_ptr<STACK_OF(X509)> caCerts(caCertsPtr, freeX509Stack); - - // Use the key & certificates - if (SSL_CTX_use_certificate(context_, cert.get()) != 1) { - return false; - } - if (SSL_CTX_use_PrivateKey(context_, privateKey.get()) != 1) { - return false; - } - for (int i = 0; i < sk_X509_num(caCerts.get()); ++i) { - SSL_CTX_add_extra_chain_cert(context_, sk_X509_value(caCerts.get(), i)); - } - return true; + boost::shared_ptr<PKCS12Certificate> pkcs12Certificate = boost::dynamic_pointer_cast<PKCS12Certificate>(certificate); + if (!pkcs12Certificate || pkcs12Certificate->isNull()) { + return false; + } + + // Create a PKCS12 structure + BIO* bio = BIO_new(BIO_s_mem()); + BIO_write(bio, vecptr(pkcs12Certificate->getData()), pkcs12Certificate->getData().size()); + boost::shared_ptr<PKCS12> pkcs12(d2i_PKCS12_bio(bio, NULL), PKCS12_free); + BIO_free(bio); + if (!pkcs12) { + return false; + } + + // Parse PKCS12 + X509 *certPtr = 0; + EVP_PKEY* privateKeyPtr = 0; + STACK_OF(X509)* caCertsPtr = 0; + SafeByteArray password(pkcs12Certificate->getPassword()); + password.push_back(0); + int result = PKCS12_parse(pkcs12.get(), reinterpret_cast<const char*>(vecptr(password)), &privateKeyPtr, &certPtr, &caCertsPtr); + if (result != 1) { + return false; + } + boost::shared_ptr<X509> cert(certPtr, X509_free); + boost::shared_ptr<EVP_PKEY> privateKey(privateKeyPtr, EVP_PKEY_free); + boost::shared_ptr<STACK_OF(X509)> caCerts(caCertsPtr, freeX509Stack); + + // Use the key & certificates + if (SSL_CTX_use_certificate(context_, cert.get()) != 1) { + return false; + } + if (SSL_CTX_use_PrivateKey(context_, privateKey.get()) != 1) { + return false; + } + for (int i = 0; i < sk_X509_num(caCerts.get()); ++i) { + SSL_CTX_add_extra_chain_cert(context_, sk_X509_value(caCerts.get(), i)); + } + return true; } std::vector<Certificate::ref> OpenSSLContext::getPeerCertificateChain() const { - std::vector<Certificate::ref> result; - STACK_OF(X509)* chain = SSL_get_peer_cert_chain(handle_); - for (int i = 0; i < sk_X509_num(chain); ++i) { - boost::shared_ptr<X509> x509Cert(X509_dup(sk_X509_value(chain, i)), X509_free); - - Certificate::ref cert = boost::make_shared<OpenSSLCertificate>(x509Cert); - result.push_back(cert); - } - return result; + std::vector<Certificate::ref> result; + STACK_OF(X509)* chain = SSL_get_peer_cert_chain(handle_); + for (int i = 0; i < sk_X509_num(chain); ++i) { + boost::shared_ptr<X509> x509Cert(X509_dup(sk_X509_value(chain, i)), X509_free); + + Certificate::ref cert = boost::make_shared<OpenSSLCertificate>(x509Cert); + result.push_back(cert); + } + return result; } boost::shared_ptr<CertificateVerificationError> OpenSSLContext::getPeerCertificateVerificationError() const { - int verifyResult = SSL_get_verify_result(handle_); - if (verifyResult != X509_V_OK) { - return boost::make_shared<CertificateVerificationError>(getVerificationErrorTypeForResult(verifyResult)); - } - else { - return boost::shared_ptr<CertificateVerificationError>(); - } + int verifyResult = SSL_get_verify_result(handle_); + if (verifyResult != X509_V_OK) { + return boost::make_shared<CertificateVerificationError>(getVerificationErrorTypeForResult(verifyResult)); + } + else { + return boost::shared_ptr<CertificateVerificationError>(); + } } ByteArray OpenSSLContext::getFinishMessage() const { - ByteArray data; - data.resize(MAX_FINISHED_SIZE); - size_t size = SSL_get_finished(handle_, vecptr(data), data.size()); - data.resize(size); - return data; + ByteArray data; + data.resize(MAX_FINISHED_SIZE); + size_t size = SSL_get_finished(handle_, vecptr(data), data.size()); + data.resize(size); + return data; } CertificateVerificationError::Type OpenSSLContext::getVerificationErrorTypeForResult(int result) { - assert(result != 0); - switch (result) { - case X509_V_ERR_CERT_NOT_YET_VALID: - case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - return CertificateVerificationError::NotYetValid; - - case X509_V_ERR_CERT_HAS_EXPIRED: - case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: - return CertificateVerificationError::Expired; - - case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: - case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: - return CertificateVerificationError::SelfSigned; - - case X509_V_ERR_CERT_UNTRUSTED: - return CertificateVerificationError::Untrusted; - - case X509_V_ERR_CERT_REJECTED: - return CertificateVerificationError::Rejected; - - case X509_V_ERR_INVALID_PURPOSE: - return CertificateVerificationError::InvalidPurpose; - - case X509_V_ERR_PATH_LENGTH_EXCEEDED: - return CertificateVerificationError::PathLengthExceeded; - - case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: - case X509_V_ERR_CERT_SIGNATURE_FAILURE: - case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: - return CertificateVerificationError::InvalidSignature; - - case X509_V_ERR_INVALID_CA: - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: - return CertificateVerificationError::InvalidCA; - - case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: - case X509_V_ERR_AKID_SKID_MISMATCH: - case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: - case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: - return CertificateVerificationError::UnknownError; - - // Unused / should not happen - case X509_V_ERR_CERT_REVOKED: - case X509_V_ERR_OUT_OF_MEM: - case X509_V_ERR_UNABLE_TO_GET_CRL: - case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: - case X509_V_ERR_CRL_SIGNATURE_FAILURE: - case X509_V_ERR_CRL_NOT_YET_VALID: - case X509_V_ERR_CRL_HAS_EXPIRED: - case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: - case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: - case X509_V_ERR_CERT_CHAIN_TOO_LONG: - case X509_V_ERR_APPLICATION_VERIFICATION: - default: - return CertificateVerificationError::UnknownError; - } + assert(result != 0); + switch (result) { + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + return CertificateVerificationError::NotYetValid; + + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + return CertificateVerificationError::Expired; + + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: + return CertificateVerificationError::SelfSigned; + + case X509_V_ERR_CERT_UNTRUSTED: + return CertificateVerificationError::Untrusted; + + case X509_V_ERR_CERT_REJECTED: + return CertificateVerificationError::Rejected; + + case X509_V_ERR_INVALID_PURPOSE: + return CertificateVerificationError::InvalidPurpose; + + case X509_V_ERR_PATH_LENGTH_EXCEEDED: + return CertificateVerificationError::PathLengthExceeded; + + case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: + case X509_V_ERR_CERT_SIGNATURE_FAILURE: + case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: + return CertificateVerificationError::InvalidSignature; + + case X509_V_ERR_INVALID_CA: + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: + return CertificateVerificationError::InvalidCA; + + case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: + case X509_V_ERR_AKID_SKID_MISMATCH: + case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: + case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: + return CertificateVerificationError::UnknownError; + + // Unused / should not happen + case X509_V_ERR_CERT_REVOKED: + case X509_V_ERR_OUT_OF_MEM: + case X509_V_ERR_UNABLE_TO_GET_CRL: + case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: + case X509_V_ERR_CRL_SIGNATURE_FAILURE: + case X509_V_ERR_CRL_NOT_YET_VALID: + case X509_V_ERR_CRL_HAS_EXPIRED: + case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: + case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: + case X509_V_ERR_CERT_CHAIN_TOO_LONG: + case X509_V_ERR_APPLICATION_VERIFICATION: + default: + return CertificateVerificationError::UnknownError; + } } } diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.h b/Swiften/TLS/OpenSSL/OpenSSLContext.h index 73fe75c..7fd5af7 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContext.h +++ b/Swiften/TLS/OpenSSL/OpenSSLContext.h @@ -17,38 +17,38 @@ namespace Swift { - class OpenSSLContext : public TLSContext, boost::noncopyable { - public: - OpenSSLContext(); - virtual ~OpenSSLContext(); + class OpenSSLContext : public TLSContext, boost::noncopyable { + public: + OpenSSLContext(); + virtual ~OpenSSLContext(); - void connect(); - bool setClientCertificate(CertificateWithKey::ref cert); + void connect(); + bool setClientCertificate(CertificateWithKey::ref cert); - void handleDataFromNetwork(const SafeByteArray&); - void handleDataFromApplication(const SafeByteArray&); + void handleDataFromNetwork(const SafeByteArray&); + void handleDataFromApplication(const SafeByteArray&); - std::vector<Certificate::ref> getPeerCertificateChain() const; - boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const; + std::vector<Certificate::ref> getPeerCertificateChain() const; + boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const; - virtual ByteArray getFinishMessage() const; + virtual ByteArray getFinishMessage() const; - private: - static void ensureLibraryInitialized(); + private: + static void ensureLibraryInitialized(); - static CertificateVerificationError::Type getVerificationErrorTypeForResult(int); + static CertificateVerificationError::Type getVerificationErrorTypeForResult(int); - void doConnect(); - void sendPendingDataToNetwork(); - void sendPendingDataToApplication(); + void doConnect(); + void sendPendingDataToNetwork(); + void sendPendingDataToApplication(); - private: - enum State { Start, Connecting, Connected, Error }; + private: + enum State { Start, Connecting, Connected, Error }; - State state_; - SSL_CTX* context_; - SSL* handle_; - BIO* readBIO_; - BIO* writeBIO_; - }; + State state_; + SSL_CTX* context_; + SSL* handle_; + BIO* readBIO_; + BIO* writeBIO_; + }; } diff --git a/Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp b/Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp index ff27b49..9f7b2aa 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp +++ b/Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp @@ -12,24 +12,24 @@ namespace Swift { bool OpenSSLContextFactory::canCreate() const { - return true; + return true; } TLSContext* OpenSSLContextFactory::createTLSContext(const TLSOptions&) { - return new OpenSSLContext(); + return new OpenSSLContext(); } void OpenSSLContextFactory::setCheckCertificateRevocation(bool check) { - if (check) { - SWIFT_LOG(warning) << "CRL Checking not supported for OpenSSL" << std::endl; - assert(false); - } + if (check) { + SWIFT_LOG(warning) << "CRL Checking not supported for OpenSSL" << std::endl; + assert(false); + } } void OpenSSLContextFactory::setDisconnectOnCardRemoval(bool check) { - if (check) { - SWIFT_LOG(warning) << "Smart cards not supported for OpenSSL" << std::endl; - } + if (check) { + SWIFT_LOG(warning) << "Smart cards not supported for OpenSSL" << std::endl; + } } diff --git a/Swiften/TLS/OpenSSL/OpenSSLContextFactory.h b/Swiften/TLS/OpenSSL/OpenSSLContextFactory.h index 21f05a4..e121a1a 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContextFactory.h +++ b/Swiften/TLS/OpenSSL/OpenSSLContextFactory.h @@ -11,13 +11,13 @@ #include <Swiften/TLS/TLSContextFactory.h> namespace Swift { - class OpenSSLContextFactory : public TLSContextFactory { - public: - bool canCreate() const; - virtual TLSContext* createTLSContext(const TLSOptions& tlsOptions); + class OpenSSLContextFactory : public TLSContextFactory { + public: + bool canCreate() const; + virtual TLSContext* createTLSContext(const TLSOptions& tlsOptions); - // Not supported - virtual void setCheckCertificateRevocation(bool b); - virtual void setDisconnectOnCardRemoval(bool b); - }; + // Not supported + virtual void setCheckCertificateRevocation(bool b); + virtual void setDisconnectOnCardRemoval(bool b); + }; } |