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-04 15:34:19 +01:00
parent 3b657701db
commit c86ad7f93b
4 changed files with 91 additions and 23 deletions

View File

@ -14,12 +14,19 @@ class BCertificate {
public:
~BCertificate();
BString String();
int Version();
time_t StartDate();
time_t ExpirationDate();
bool IsValidAuthority();
bool IsSelfSigned();
BString Issuer();
BString Subject();
BString SignatureAlgorithm();
BString String();
private:
friend class BSecureSocket::Private;

View File

@ -21,7 +21,7 @@ public:
virtual ~BSecureSocket();
virtual bool CertificateVerificationFailed(BCertificate&
certificate);
certificate, const char* message);
// BSocket implementation

View File

@ -14,6 +14,9 @@
#ifdef OPENSSL_ENABLED
#include <openssl/x509v3.h>
static time_t
parse_ASN1(ASN1_GENERALIZEDTIME *asn1)
{
@ -61,18 +64,10 @@ BCertificate::~BCertificate()
}
BString
BCertificate::String()
int
BCertificate::Version()
{
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;
return X509_get_version(fPrivate->fX509) + 1;
}
@ -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
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
@ -128,13 +166,6 @@ BCertificate::~BCertificate()
}
BString
BCertificate::String()
{
return BString();
}
time_t
BCertificate::StartDate()
{
@ -149,6 +180,20 @@ BCertificate::ExpirationDate()
}
bool
BCertificate::IsValidAuthority()
{
return false;
}
int
BCertificate::Version()
{
return B_NOT_SUPPORTED;
}
BString
BCertificate::Issuer()
{
@ -163,4 +208,18 @@ BCertificate::Subject()
}
BString
BCertificate::SignatureAlgorithm()
{
return BString();
}
BString
BCertificate::String()
{
return BString();
}
#endif

View File

@ -156,9 +156,12 @@ BSecureSocket::Private::VerifyCallback(int ok, X509_STORE_CTX* ctx)
if (certificate == NULL)
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.
BCertificate failedCertificate(certificate);
return socket->CertificateVerificationFailed(failedCertificate);
return socket->CertificateVerificationFailed(failedCertificate, message);
}
@ -289,12 +292,11 @@ BSecureSocket::WaitForReadable(bigtime_t timeout) const
bool
BSecureSocket::CertificateVerificationFailed(BCertificate& certificate)
BSecureSocket::CertificateVerificationFailed(BCertificate&, const char*)
{
// Until apps actually make use of the certificate API, let's keep the old
// behavior and accept all connections, even if the certificate validation
// didn't work.
(void)certificate;
return true;
}