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:
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user