BHttpRequest: add SSL certificate exception management.

When an HTTPS request uses an SSL certificate that OpenSSL considers
untrusted, and the user decides to continue anyway, add the certificate
to an exception list. Match certificates against this list and don't ask
the user again if they are already there.

Fixes #12004. Thanks to markh for the initial patch and peeking into the
WebKit code!
This commit is contained in:
Adrien Destugues 2015-11-09 10:46:58 +01:00
parent f26dbfe79b
commit 4849ab6c8b
5 changed files with 55 additions and 11 deletions

View File

@ -29,7 +29,7 @@ public:
BString String() const;
bool operator==(const BCertificate& other);
bool operator==(const BCertificate& other) const;
private:
friend class BSecureSocket::Private;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2010-2014 Haiku Inc. All rights reserved.
* Copyright 2010-2015 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
@ -8,6 +8,7 @@
#define _B_URL_CONTEXT_H_
#include <Certificate.h>
#include <HttpAuthentication.h>
#include <NetworkCookieJar.h>
#include <Referenceable.h>
@ -30,6 +31,7 @@ public:
void AddAuthentication(const BUrl& url,
const BHttpAuthentication& authentication);
void SetProxy(BString host, uint16 port);
void AddCertificateException(const BCertificate& certificate);
// Context accessors
BNetworkCookieJar& GetCookieJar();
@ -37,12 +39,15 @@ public:
bool UseProxy();
BString GetProxyHost();
uint16 GetProxyPort();
bool HasCertificateException(const BCertificate& certificate);
private:
BNetworkCookieJar fCookieJar;
typedef BPrivate::SynchronizedHashMap<BPrivate::HashString,
BHttpAuthentication*> BHttpAuthenticationMap;
BHttpAuthenticationMap* fAuthenticationMap;
typedef BObjectList<const BCertificate> BCertificateSet;
BCertificateSet fCertificates;
BString fProxyHost;
uint16 fProxyPort;

View File

@ -60,7 +60,7 @@ BCertificate::BCertificate(Private* data)
BCertificate::BCertificate(const BCertificate& other)
{
fPrivate = new(std::nothrow) BCertificate::Private(other.fPrivate);
fPrivate = new(std::nothrow) BCertificate::Private(other.fPrivate->fX509);
}
@ -151,7 +151,7 @@ BCertificate::String() const
bool
BCertificate::operator==(const BCertificate& other)
BCertificate::operator==(const BCertificate& other) const
{
return X509_cmp(fPrivate->fX509, other.fPrivate->fX509) == 0;
}
@ -168,7 +168,7 @@ BCertificate::Private::Private(X509* data)
BCertificate::Private::~Private()
{
sk_X509_pop_free(fX509, X509_free);
X509_free(fX509);
}
@ -247,7 +247,7 @@ BCertificate::String() const
bool
BCertificate::operator==(const BCertificate& other)
BCertificate::operator==(const BCertificate& other) const
{
return false;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2010-2014 Haiku Inc. All rights reserved.
* Copyright 2010-2015 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -1083,9 +1083,14 @@ bool
BHttpRequest::_CertificateVerificationFailed(BCertificate& certificate,
const char* message)
{
if (fListener != NULL) {
return fListener->CertificateVerificationFailed(this, certificate,
message);
if (fContext->HasCertificateException(certificate))
return true;
if (fListener != NULL
&& fListener->CertificateVerificationFailed(this, certificate, message)) {
// User asked us to continue anyway, let's add a temporary exception for this certificate
fContext->AddCertificateException(certificate);
return true;
}
return false;

View File

@ -1,9 +1,10 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Copyright 2010-2015 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Christophe Huriaux, c.huriaux@gmail.com
* Adrien Destugues, pulkomandy@pulkomandy.tk
*/
@ -19,6 +20,7 @@ BUrlContext::BUrlContext()
:
fCookieJar(),
fAuthenticationMap(NULL),
fCertificates(20, true),
fProxyHost(),
fProxyPort(0)
{
@ -84,6 +86,16 @@ BUrlContext::SetProxy(BString host, uint16 port)
}
void
BUrlContext::AddCertificateException(const BCertificate& certificate)
{
BCertificate* copy = new(std::nothrow) BCertificate(certificate);
if (copy != NULL) {
fCertificates.AddItem(copy);
}
}
// #pragma mark Context accessors
@ -133,3 +145,25 @@ BUrlContext::GetProxyPort()
{
return fProxyPort;
}
bool
BUrlContext::HasCertificateException(const BCertificate& certificate)
{
struct Equals: public UnaryPredicate<const BCertificate> {
Equals(const BCertificate& itemToMatch)
:
fItemToMatch(itemToMatch)
{
}
int operator()(const BCertificate* item) const
{
return *item == fItemToMatch;
}
const BCertificate& fItemToMatch;
} comparator(certificate);
return fCertificates.FindIf(comparator) != NULL;
}