Add more features in BCertificate class

* Make it possible to extract more useful data from the certificate
* Also get the OpenSSL error message when a certificate can't be
validated. Send it to the verification failure callback so it can be
shown to the user.
This commit is contained in:
Adrien Destugues
2014-11-06 15:01:59 +01:00
parent 3b657701db
commit c86ad7f93b
4 changed files with 91 additions and 23 deletions
+8 -1
View File
@@ -14,12 +14,19 @@ class BCertificate {
public: public:
~BCertificate(); ~BCertificate();
BString String(); int Version();
time_t StartDate(); time_t StartDate();
time_t ExpirationDate(); time_t ExpirationDate();
bool IsValidAuthority();
bool IsSelfSigned();
BString Issuer(); BString Issuer();
BString Subject(); BString Subject();
BString SignatureAlgorithm();
BString String();
private: private:
friend class BSecureSocket::Private; friend class BSecureSocket::Private;
+1 -1
View File
@@ -21,7 +21,7 @@ public:
virtual ~BSecureSocket(); virtual ~BSecureSocket();
virtual bool CertificateVerificationFailed(BCertificate& virtual bool CertificateVerificationFailed(BCertificate&
certificate); certificate, const char* message);
// BSocket implementation // BSocket implementation
+77 -18
View File
@@ -14,6 +14,9 @@
#ifdef OPENSSL_ENABLED #ifdef OPENSSL_ENABLED
#include <openssl/x509v3.h>
static time_t static time_t
parse_ASN1(ASN1_GENERALIZEDTIME *asn1) parse_ASN1(ASN1_GENERALIZEDTIME *asn1)
{ {
@@ -61,18 +64,10 @@ BCertificate::~BCertificate()
} }
BString int
BCertificate::String() BCertificate::Version()
{ {
BIO *buffer = BIO_new(BIO_s_mem()); return X509_get_version(fPrivate->fX509) + 1;
X509_print_ex(buffer, fPrivate->fX509, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
char* pointer;
long length = BIO_get_mem_data(buffer, &pointer);
BString result(pointer, length);
BIO_free(buffer);
return result;
} }
@@ -90,6 +85,20 @@ BCertificate::ExpirationDate()
} }
bool
BCertificate::IsValidAuthority()
{
return X509_check_ca(fPrivate->fX509) > 0;
}
bool
BCertificate::IsSelfSigned()
{
return X509_check_issued(fPrivate->fX509, fPrivate->fX509) == X509_V_OK;
}
BString BString
BCertificate::Issuer() BCertificate::Issuer()
{ {
@@ -106,6 +115,35 @@ BCertificate::Subject()
} }
BString
BCertificate::SignatureAlgorithm()
{
int algorithmIdentifier = OBJ_obj2nid(
fPrivate->fX509->cert_info->key->algor->algorithm);
if (algorithmIdentifier == NID_undef)
return BString("undefined");
const char* buffer = OBJ_nid2ln(algorithmIdentifier);
return BString(buffer);
}
BString
BCertificate::String()
{
BIO *buffer = BIO_new(BIO_s_mem());
X509_print_ex(buffer, fPrivate->fX509, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
char* pointer;
long length = BIO_get_mem_data(buffer, &pointer);
BString result(pointer, length);
BIO_free(buffer);
return result;
}
// #pragma mark - BCertificate::Private // #pragma mark - BCertificate::Private
@@ -128,13 +166,6 @@ BCertificate::~BCertificate()
} }
BString
BCertificate::String()
{
return BString();
}
time_t time_t
BCertificate::StartDate() BCertificate::StartDate()
{ {
@@ -149,6 +180,20 @@ BCertificate::ExpirationDate()
} }
bool
BCertificate::IsValidAuthority()
{
return false;
}
int
BCertificate::Version()
{
return B_NOT_SUPPORTED;
}
BString BString
BCertificate::Issuer() BCertificate::Issuer()
{ {
@@ -163,4 +208,18 @@ BCertificate::Subject()
} }
BString
BCertificate::SignatureAlgorithm()
{
return BString();
}
BString
BCertificate::String()
{
return BString();
}
#endif #endif
+5 -3
View File
@@ -156,9 +156,12 @@ BSecureSocket::Private::VerifyCallback(int ok, X509_STORE_CTX* ctx)
if (certificate == NULL) if (certificate == NULL)
return 0; return 0;
int error = X509_STORE_CTX_get_error(ctx);
const char* message = X509_verify_cert_error_string(error);
// Let the BSecureSocket (or subclass) decide if we should continue anyway. // Let the BSecureSocket (or subclass) decide if we should continue anyway.
BCertificate failedCertificate(certificate); BCertificate failedCertificate(certificate);
return socket->CertificateVerificationFailed(failedCertificate); return socket->CertificateVerificationFailed(failedCertificate, message);
} }
@@ -289,12 +292,11 @@ BSecureSocket::WaitForReadable(bigtime_t timeout) const
bool bool
BSecureSocket::CertificateVerificationFailed(BCertificate& certificate) BSecureSocket::CertificateVerificationFailed(BCertificate&, const char*)
{ {
// Until apps actually make use of the certificate API, let's keep the old // Until apps actually make use of the certificate API, let's keep the old
// behavior and accept all connections, even if the certificate validation // behavior and accept all connections, even if the certificate validation
// didn't work. // didn't work.
(void)certificate;
return true; return true;
} }