summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2010-11-07 12:31:41 (GMT)
committerRemko Tronçon <git@el-tramo.be>2010-11-07 14:18:04 (GMT)
commit70d19e3b5d3757310caf32e1732cac2cd4ae0a63 (patch)
treedb1e206fd1164d85c5e00b408e9dd5ed728a7ed6 /Swiften/TLS/OpenSSL
parent647e2cc6fc6bc1764c1bf449b4110917f6c723df (diff)
downloadswift-contrib-70d19e3b5d3757310caf32e1732cac2cd4ae0a63.zip
swift-contrib-70d19e3b5d3757310caf32e1732cac2cd4ae0a63.tar.bz2
Added certificate verification API to TLS context.
Diffstat (limited to 'Swiften/TLS/OpenSSL')
-rw-r--r--Swiften/TLS/OpenSSL/OpenSSLContext.cpp74
-rw-r--r--Swiften/TLS/OpenSSL/OpenSSLContext.h3
2 files changed, 74 insertions, 3 deletions
diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
index 80575ca..234c831 100644
--- a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
+++ b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
@@ -7,6 +7,7 @@
#include <vector>
#include <openssl/err.h>
#include <openssl/pkcs12.h>
+#include <openssl/x509v3.h>
#include "Swiften/TLS/OpenSSL/OpenSSLContext.h"
#include "Swiften/TLS/PKCS12Certificate.h"
@@ -56,14 +57,14 @@ void OpenSSLContext::doConnect() {
int connectResult = SSL_connect(handle_);
int error = SSL_get_error(handle_, connectResult);
switch (error) {
- case SSL_ERROR_NONE:
+ case SSL_ERROR_NONE: {
state_ = Connected;
- onConnected();
- //X509* x = SSL_get_peer_certificate(handle_);
//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;
@@ -162,4 +163,71 @@ bool OpenSSLContext::setClientCertificate(const PKCS12Certificate& certificate)
return true;
}
+Certificate::ref OpenSSLContext::getPeerCertificate() const {
+ boost::shared_ptr<X509> x509Cert(SSL_get_peer_certificate(handle_), X509_free);
+ if (x509Cert) {
+ Certificate::ref certificate(new Certificate());
+
+ // Common name
+ X509_NAME* subjectName = X509_get_subject_name(x509Cert.get());
+ if (subjectName) {
+ int cnLoc = X509_NAME_get_index_by_NID(subjectName, NID_commonName, -1);
+ if (cnLoc != -1) {
+ X509_NAME_ENTRY* cnEntry = X509_NAME_get_entry(subjectName, cnLoc);
+ ASN1_STRING* cnData = X509_NAME_ENTRY_get_data(cnEntry);
+ certificate->setCommonName(ByteArray(cnData->data, cnData->length).toString());
+ }
+ }
+
+ // subjectAltNames
+ int subjectAltNameLoc = X509_get_ext_by_NID(x509Cert.get(), NID_subject_alt_name, -1);
+ if(subjectAltNameLoc != -1) {
+ X509_EXTENSION* extension = X509_get_ext(x509Cert.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;
+ certificate->addXMPPAddress(ByteArray(ASN1_STRING_data(xmppAddrValue), ASN1_STRING_length(xmppAddrValue)).toString());
+ }
+ 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;
+ certificate->addSRVName(ByteArray(ASN1_STRING_data(srvNameValue), ASN1_STRING_length(srvNameValue)).toString());
+ }
+ }
+ else if (generalName->type == GEN_DNS) {
+ // DNSName
+ certificate->addDNSName(ByteArray(ASN1_STRING_data(generalName->d.dNSName), ASN1_STRING_length(generalName->d.dNSName)).toString());
+ }
+ }
+ }
+ return certificate;
+ }
+ else {
+ return Certificate::ref();
+ }
+}
+
+boost::optional<CertificateVerificationError> OpenSSLContext::getPeerCertificateVerificationError() const {
+ long verifyResult = SSL_get_verify_result(handle_);
+ if (verifyResult != X509_V_OK) {
+ return CertificateVerificationError();
+ }
+ else {
+ return boost::optional<CertificateVerificationError>();
+ }
+}
+
}
diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.h b/Swiften/TLS/OpenSSL/OpenSSLContext.h
index a01e3e5..a0e73c4 100644
--- a/Swiften/TLS/OpenSSL/OpenSSLContext.h
+++ b/Swiften/TLS/OpenSSL/OpenSSLContext.h
@@ -27,6 +27,9 @@ namespace Swift {
void handleDataFromNetwork(const ByteArray&);
void handleDataFromApplication(const ByteArray&);
+ Certificate::ref getPeerCertificate() const;
+ boost::optional<CertificateVerificationError> getPeerCertificateVerificationError() const;
+
private:
static void ensureLibraryInitialized();