BHttpRequest: propagate SSL errors to listener

This way it's possible to handle them in applications.
This commit is contained in:
Adrien Destugues
2014-11-06 15:02:00 +01:00
parent c86ad7f93b
commit 5ee2151e2c
7 changed files with 146 additions and 34 deletions
+7
View File
@@ -8,6 +8,7 @@
#include <deque> #include <deque>
#include <Certificate.h>
#include <HttpForm.h> #include <HttpForm.h>
#include <HttpHeaders.h> #include <HttpHeaders.h>
#include <HttpResult.h> #include <HttpResult.h>
@@ -74,6 +75,12 @@ private:
void _SetResultStatusCode(int32 statusCode); void _SetResultStatusCode(int32 statusCode);
BString& _ResultStatusText(); BString& _ResultStatusText();
// SSL failure management
friend class CheckedSecureSocket;
bool _CertificateVerificationFailed(
BCertificate& certificate,
const char* message);
// Utility methods // Utility methods
bool _IsDefaultPort(); bool _IsDefaultPort();
@@ -26,7 +26,8 @@ enum {
B_URL_PROTOCOL_DATA_RECEIVED, B_URL_PROTOCOL_DATA_RECEIVED,
B_URL_PROTOCOL_DOWNLOAD_PROGRESS, B_URL_PROTOCOL_DOWNLOAD_PROGRESS,
B_URL_PROTOCOL_UPLOAD_PROGRESS, B_URL_PROTOCOL_UPLOAD_PROGRESS,
B_URL_PROTOCOL_REQUEST_COMPLETED B_URL_PROTOCOL_REQUEST_COMPLETED,
B_URL_PROTOCOL_CERTIFICATE_VERIFICATION_FAILED
}; };
@@ -52,6 +53,10 @@ public:
ssize_t bytesSent, ssize_t bytesTotal); ssize_t bytesSent, ssize_t bytesTotal);
virtual void RequestCompleted(BUrlRequest* caller, virtual void RequestCompleted(BUrlRequest* caller,
bool success); bool success);
virtual bool CertificateVerificationFailed(
BUrlRequest* caller,
BCertificate& certificate,
const char* message);
private: private:
void _SendMessage(BMessage* message, void _SendMessage(BMessage* message,
+15
View File
@@ -9,6 +9,8 @@
#include <stddef.h> #include <stddef.h>
#include <cstdlib> #include <cstdlib>
class BCertificate;
class BUrlRequest; class BUrlRequest;
@@ -117,6 +119,19 @@ public:
virtual void DebugMessage(BUrlRequest* caller, virtual void DebugMessage(BUrlRequest* caller,
BUrlProtocolDebugMessage type, BUrlProtocolDebugMessage type,
const char* text); const char* text);
/**
CertificateVerificationFailed(certificate, message)
Frequency: Once
Parameters: certificate SSL certificate which coulnd't be validated
message error message describing the problem
Return true to proceed anyway, false to abort the connection
*/
virtual bool CertificateVerificationFailed(
BUrlRequest* caller,
BCertificate& certificate,
const char* message);
}; };
#endif // _B_URL_PROTOCOL_LISTENER_H_ #endif // _B_URL_PROTOCOL_LISTENER_H_
+47 -3
View File
@@ -19,6 +19,7 @@
#include <new> #include <new>
#include <AutoDeleter.h> #include <AutoDeleter.h>
#include <Certificate.h>
#include <Debug.h> #include <Debug.h>
#include <DynamicBuffer.h> #include <DynamicBuffer.h>
#include <File.h> #include <File.h>
@@ -31,6 +32,35 @@
static const int32 kHttpBufferSize = 4096; static const int32 kHttpBufferSize = 4096;
class CheckedSecureSocket: public BSecureSocket
{
public:
CheckedSecureSocket(BHttpRequest* request);
bool CertificateVerificationFailed(BCertificate& certificate,
const char* message);
private:
BHttpRequest* fRequest;
};
CheckedSecureSocket::CheckedSecureSocket(BHttpRequest* request)
:
BSecureSocket(),
fRequest(request)
{
}
bool
CheckedSecureSocket::CertificateVerificationFailed(BCertificate& certificate,
const char* message)
{
return fRequest->_CertificateVerificationFailed(certificate, message);
}
BHttpRequest::BHttpRequest(const BUrl& url, bool ssl, const char* protocolName, BHttpRequest::BHttpRequest(const BUrl& url, bool ssl, const char* protocolName,
BUrlProtocolListener* listener, BUrlContext* context) BUrlProtocolListener* listener, BUrlContext* context)
: :
@@ -50,7 +80,7 @@ BHttpRequest::BHttpRequest(const BUrl& url, bool ssl, const char* protocolName,
{ {
_ResetOptions(); _ResetOptions();
if (fSSL) if (fSSL)
fSocket = new(std::nothrow) BSecureSocket(); fSocket = new(std::nothrow) CheckedSecureSocket(this);
else else
fSocket = new(std::nothrow) BSocket(); fSocket = new(std::nothrow) BSocket();
} }
@@ -76,7 +106,7 @@ BHttpRequest::BHttpRequest(const BHttpRequest& other)
_ResetOptions(); _ResetOptions();
// FIXME some options may be copied from other instead. // FIXME some options may be copied from other instead.
if (fSSL) if (fSSL)
fSocket = new(std::nothrow) BSecureSocket(); fSocket = new(std::nothrow) CheckedSecureSocket(this);
else else
fSocket = new(std::nothrow) BSocket(); fSocket = new(std::nothrow) BSocket();
} }
@@ -1022,7 +1052,21 @@ BHttpRequest::_ResultStatusText()
} }
bool BHttpRequest::_IsDefaultPort() bool
BHttpRequest::_CertificateVerificationFailed(BCertificate& certificate,
const char* message)
{
if (fListener != NULL) {
return fListener->CertificateVerificationFailed(this, certificate,
message);
}
return false;
}
bool
BHttpRequest::_IsDefaultPort()
{ {
if (fSSL && Url().Port() == 443) if (fSSL && Url().Port() == 443)
return true; return true;
@@ -142,6 +142,20 @@ BUrlProtocolAsynchronousListener::MessageReceived(BMessage* message)
} }
break; break;
case B_URL_PROTOCOL_CERTIFICATE_VERIFICATION_FAILED:
{
const char* error = message->FindString("url:error");
BCertificate* certificate;
message->FindPointer("url:certificate", (void**)&certificate);
bool result = CertificateVerificationFailed(caller,
*certificate, error);
BMessage reply;
reply.AddBool("url:continue", result);
message->SendReply(&reply);
}
break;
default: default:
PRINT(("BUrlProtocolAsynchronousListener: Unknown notification %d\n", PRINT(("BUrlProtocolAsynchronousListener: Unknown notification %d\n",
notification)); notification));
@@ -125,6 +125,25 @@ BUrlProtocolDispatchingListener::RequestCompleted(BUrlRequest* caller,
} }
bool
BUrlProtocolDispatchingListener::CertificateVerificationFailed(
BUrlRequest* caller, BCertificate& certificate, const char* error)
{
BMessage message(B_URL_PROTOCOL_NOTIFICATION);
message.AddString("url:error", error);
message.AddPointer("url:certificate", &certificate);
message.AddInt8(kUrlProtocolMessageType,
B_URL_PROTOCOL_CERTIFICATE_VERIFICATION_FAILED);
message.AddPointer(kUrlProtocolCaller, caller);
// Warning: synchronous reply
BMessage reply;
fMessenger.SendMessage(&message, &reply);
return reply.FindBool("url:continue");
}
void void
BUrlProtocolDispatchingListener::_SendMessage(BMessage* message, BUrlProtocolDispatchingListener::_SendMessage(BMessage* message,
int8 notification, BUrlRequest* caller) int8 notification, BUrlRequest* caller)
@@ -27,6 +27,14 @@ BUrlProtocolListener::HostnameResolved(BUrlRequest*, const char*)
} }
bool
BUrlProtocolListener::CertificateVerificationFailed(BUrlRequest* caller,
BCertificate& certificate, const char* message)
{
return false;
}
void void
BUrlProtocolListener::ResponseStarted(BUrlRequest*) BUrlProtocolListener::ResponseStarted(BUrlRequest*)
{ {