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:
parent
3b657701db
commit
c86ad7f93b
@ -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;
|
||||
|
@ -21,7 +21,7 @@ public:
|
||||
virtual ~BSecureSocket();
|
||||
|
||||
virtual bool CertificateVerificationFailed(BCertificate&
|
||||
certificate);
|
||||
certificate, const char* message);
|
||||
|
||||
// BSocket implementation
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user